fax T30 T38协议二进制分析

1 数据流模式

1 F1(cng)->

2 F2(cng)<-

3 DIS <-

4 DCS->

5 TCF->

6 CFR FTT<-

7 传真报文->

8 MPS EOM EOP->

9MCF<-

10 DCN

2 ECM模式

1 F1(cng)->

2 F2(cng)<-

3 DIS <-

4 DCS->

5 TCF->

6 CFR FTT<-

7 传真报文->

8 PPS-NULL->

9 PPS-EOP->

10 MCF<-

11 DCN

3 hdlc帧结构

1 F标志

2 A地址

3 C控制

FCF传真控制字

DIS表征被叫终端的表征能力
DCS数字建立命令,对DIS的响应
TCF用于检验训练,
CFR可以接受的证实
FTT训练失败
EOM报文结束
MPS多页信号
EOP过程结束
PPS部分页信号
MCF报文证实
PPR部分页请求
DCN切断命令

4 I 信息

FIF传真信息字段包含相应的参数和信息

通常是8字节

5 FCS检查

6 F标志


4 DIS消息例子

ff标志
13地址
80控制字DIS
00data
eedata
a8data
c4data
80data
11data
e7data
b3data
10CRC
03CRC

    s->hudptl = udptl_init(t38_core_rx_ifp_packet, s);

int32_t udptl_recv_proc(void* handle, uint8_t* buf, int32_t len)
{
    struct udptl_struct *s =(struct udptl_struct *) handle;

    len = udptl_rx_packet(s, buf, len);
    if(len < 1){
        return -1;
    }
    flog("step1.01");
    if(s->cb){
        s->cb(s->data, s->f, len);
    }
    
    return 0;
}

void* udptl_init(udptl_callback_t cb, void* data)
{
    struct udptl_struct *s;

    s = malloc(sizeof(*s));
    if(NULL == s){
        return NULL;
    }

    memset(s, 0, sizeof(*s));
    s->cb = cb;
    s->data = data;

    return s;
}


int32_t t38_core_rx_ifp_packet(void* data, struct frame *f, int32_t total)
{
    t38_state_t s =(t38_state_t) data;
    int32_t i;
    int32_t t30_indicator;
    int32_t t30_data;
    int32_t ptr;
    int32_t other_half;
    int32_t numocts;
    const uint8_t *msg;
    uint32_t count;
    uint32_t t30_field_type;
    uint8_t type;
    uint8_t data_field_present;
    uint8_t field_data_present;
    uint8_t tag[20];
    int32_t seq_no = f->seq;
    uint8_t *buf = f->data;
    int len = f->len;
    
    if(len < 1){
        return -1;
    }
    
    if(s->check_sequence_numbers){
        seq_no &= 0xFFFF;
        if(seq_no != s->rx_expected_seq_no){
            /* An expected value of -1 indicates this is the first received packet, and will accept
               anything for that. We can't assume they will start from zero, even though they should. */
            if(s->rx_expected_seq_no != -1){
                /* We have a packet with a serial number that is not in sequence. The cause could be:
                    - 1. a repeat copy of a recent packet. Many T.38 implementations can preduce quite a lot of these.
                    - 2. a late packet, whose point in the sequence we have already passed.
                    - 3. the result of a hop in the sequence numbers cause by something weird from the other
                         end. Stream switching might cause this
                    - 4. missing packets.
                
                    In cases 1 and 2 we need to drop this packet. In case 2 it might make sense to try to do
                    something with it in the terminal case. Currently we don't. For gateway operation it will be
                    too late to do anything useful.
                 */
                if(((seq_no + 1) & 0xFFFF) == s->rx_expected_seq_no){
                    /* Assume this is truly a repeat packet, and don't bother checking its contents. */
                    return 0;
                }
                /* Distinguish between a little bit out of sequence, and a huge hop. */
                switch(classify_seq_no_offset(s->rx_expected_seq_no, seq_no))
                {
                case -1:
                    /* This packet is in the near past, so its late. */
                    return 0;
                case 1:
                    /* This packet is in the near future, so some packets have been lost */
                    s->ops->missing(s, s->rx_data, s->rx_expected_seq_no, seq_no);
                    s->missing_packets += (seq_no - s->rx_expected_seq_no);
                    break;
                default:
                    /* The sequence has jumped wildly */
                    s->ops->missing(s, s->rx_data, -1, -1);
                    s->missing_packets++;
                    break;
                }
            }
            s->rx_expected_seq_no = seq_no;
        }
    }
    /* The sequence numbering is defined as rolling from 0xFFFF to 0x0000. Some implementations
       of T.38 roll from 0xFFFF to 0x0001. Isn't standardisation a wonderful thing? The T.38
       document specifies only a small fraction of what it should, yet then they actually nail
       something properly, people ignore it. Developers in this industry truly deserves the ****
       **** **** **** **** **** documents they have to live with. Anyway, when the far end has a
       broken rollover behaviour we will get a hiccup at the rollover point. Don't worry too
       much. We will just treat the message in progress as one with some missing data. With any
       luck a retry will ride over the problem. Rollovers don't occur that often. It takes quite
       a few FAX pages to reach rollover. */
    s->rx_expected_seq_no = (s->rx_expected_seq_no + 1) & 0xFFFF;
    data_field_present = (buf[0] >> 7) & 1;
    type = (buf[0] >> 6) & 1;
    ptr = 0;
    switch (type)
    {
    case T38_TYPE_OF_MSG_T30_INDICATOR:
        /* Indicators should never have a data field */
        if(data_field_present){
            return -1;
        }
        /* Any received indicator should mean we no longer have a valid concept of "last received data/field type". */
        s->current_rx_data_type = -1;
        s->current_rx_field_type = -1;
        if (buf[0] & 0x20){
            /* Extension */
            if(len != 2){
                return -1;
            }
            t30_indicator = T38_IND_V8_ANSAM + (((buf[0] << 2) & 0x3C) | ((buf[1] >> 6) & 0x3));
            if(t30_indicator > T38_IND_V33_14400_TRAINING){
                return -1;
            }
        }
        else{
            if(len != 1){
                return -1;
            }
            t30_indicator = (buf[0] >> 1) & 0xF;
        }
        
        s->ops->indicator(s, s->rx_data, t30_indicator);
        /* This must come after the indicator handler, so the handler routine sees the existing state of the
           indicator. */
        s->current_rx_indicator = t30_indicator;
        break;
    case T38_TYPE_OF_MSG_T30_DATA:
        if(buf[0] & 0x20){
            /* Extension */
            if(len < 2){
                return -1;
            }
            
            t30_data = T38_DATA_V8 + (((buf[0] << 2) & 0x3C) | ((buf[1] >> 6) & 0x3));
            if(t30_data > T38_DATA_V33_14400){
                return -1;
            }
            ptr = 2;
        }
        else{
            t30_data = (buf[0] >> 1) & 0xF;
            if(t30_data > T38_DATA_V17_14400){
                return -1;
            }
            ptr = 1;
        }
        
        if(!data_field_present){
            /* This is kinda weird, but I guess if the length checks out we accept it. */
            if(ptr != len){
                return -1;
            }
            break;
        }
        if(ptr >= len){
            return -1;
        }
        
        count = buf[ptr++];
        other_half = 0;
        t30_field_type = 0;
        for(i = 0;  i < (int32_t) count;  i++){
            if(ptr >= len){
                return -1;
            }
            
            if(s->t38_version == 0){
                /* The original version of T.38 with a typo in the ASN.1 spec. */
                if(other_half){
                    /* The lack of a data field in the previous message means
                    we are currently in the middle of an octet. */
                    field_data_present = (buf[ptr] >> 3) & 1;
                    /* Decode field_type */
                    t30_field_type = buf[ptr] & 0x7;
                    ptr++;
                    other_half = 0;
                }
                else{
                    field_data_present = (buf[ptr] >> 7) & 1;
                    /* Decode field_type */
                    t30_field_type = (buf[ptr] >> 4) & 0x7;
                    if(field_data_present){
                        ptr++;
                    }
                    else{
                        other_half = 1;
                    }
                }
                
                if(t30_field_type > T38_FIELD_T4_NON_ECM_SIG_END){
                    return -1;
                }
            }
            else{
                field_data_present = (buf[ptr] >> 7) & 1;
                /* Decode field_type */
                if(buf[ptr] & 0x40){
                    if(ptr > len - 2){
                        return -1;
                    }
                    t30_field_type = T38_FIELD_CM_MESSAGE + (((buf[ptr] << 2) & 0x3C) | ((buf[ptr + 1] >> 6) & 0x3));        
                    if(t30_field_type > T38_FIELD_V34RATE){
                        return -1;
                    }
                    ptr += 2;
                }
                else{
                    t30_field_type = (buf[ptr++] >> 3) & 0x7;
                }
            }
            
            /* Decode field_data */
            if(field_data_present){
                if(ptr > len - 2){
                    return -1;
                }
                
                numocts = ((buf[ptr] << 8) | buf[ptr + 1]) + 1;
                msg = buf + ptr + 2;
                ptr += numocts + 2;
            }
            else{
                numocts = 0;
                msg = NULL;
            }
            
            if(ptr > len){
                return -1;
            }
            
            s->ops->data_proc(s, s->rx_data, t30_data, t30_field_type, msg, numocts);
            s->current_rx_data_type = t30_data;
            s->current_rx_field_type = t30_field_type;
        }
        if(ptr != len){
            if(s->t38_version != 0 || ptr != (len - 1) || !other_half){
                return -1;
            }
        }
        break;
    }
    
    return 0;
}


static int32_t terminal_t38_fe_init(terminal_state_t t, int ecm, int rd_cnt)
{
    front_end_state_t *s;
    
    #if defined(WIN32)
    static struct t38_ops ops;
    ops.indicator = process_rx_indicator;
    ops.data_proc = process_rx_data;
    ops.missing = process_rx_missing;
    #else
    static struct t38_ops ops = {
        .indicator = process_rx_indicator,
        .data_proc = process_rx_data,
        .missing = process_rx_missing,
    };
    #endif
    s = &t->t38_fe;
    s->t38 = t38_core_init(&ops, ecm, rd_cnt, t);
    if(NULL == s->t38){
        return -1;
    }
    
    t38_set_fastest_image_data_rate(s->t38, 14400);
    
    s->rx_signal_present = 0;
    s->timed_step = T38_TIMED_STEP_NONE;
    //s->iaf = T30_IAF_MODE_T37 | T30_IAF_MODE_T38;
    s->iaf = T30_IAF_MODE_T38;
    
    s->current_tx_data_type = T38_DATA_NONE;
    s->next_tx_samples = 0;
    s->chunking_modes = T38_CHUNKING_ALLOW_TEP_TIME;
    
    s->hdlc_tx.ptr = 0;
    
    return 0;
}

            s->ops->data_proc(s, s->rx_data, t30_data, t30_field_type, msg, numocts);
            s->current_rx_data_type = t30_data;
            s->current_rx_field_type = t30_field_type;


static int32_t process_rx_data(t38_state_t t, void *user_data, int32_t data_type, int32_t field_type, const uint8_t *buf, int32_t len)
{
    terminal_state_t s =(struct terminal_state *) user_data;
    front_end_state_t *fe;
#if defined(_MSC_VER)
    uint8_t *buf2 = (uint8_t *) malloc/*_alloca*/(len);
#else
    uint8_t buf2[len];
#endif
    
    fe = &s->t38_fe;
    
    /* Protect against T.38 stuff arriving after we've actually finished. */
    if(fe->current_rx_type == T30_MODEM_DONE){
        return 0;
    }
    
    /* In termination mode we don't care very much what the data type is apart from a couple of special cases. */
    switch(data_type)
    {
    case T38_DATA_V8:
        return 0;
    case T38_DATA_V34_PRI_RATE:
        switch (field_type)
        {
        case T38_FIELD_V34RATE:
            if(len >= 3){
                fe->t38->v34_rate = t38_v34rate_to_bps(buf, len);
            }
            break;
        default:
            break;
        }
        
        return 0;
    default:
        break;
    }
    
    switch (field_type)
    {
    case T38_FIELD_HDLC_DATA:
        if(fe->timeout_rx_samples == 0){
            /* HDLC can just start without any signal indicator on some platforms, even when
                there is zero packet loss. Nasty, but 1. Its a good idea to be tolerant of
                loss, though, so accepting a sudden start of HDLC data is the right thing to do. */
            fake_rx_indicator(t, s, T38_IND_V21_PREAMBLE);
            /* All real HDLC messages in the FAX world start with 0xFF. If this one is not starting
                with 0xFF it would appear some octets must have been missed before this one. */
            if(len <= 0 || buf[0] != 0xFF)
                fe->rx_data_missing = 1;
        }
        
        if(len > 0){
            if(fe->hdlc_rx.len + len <= T38_MAX_HDLC_LEN){
                bit_reverse(fe->hdlc_rx.buf + fe->hdlc_rx.len, buf, len);
                fe->hdlc_rx.len += len;
            }
            else{
                fe->rx_data_missing = 1;
            }
        }
        
        fe->timeout_rx_samples = fe->samples + ms_to_samples(MID_RX_TIMEOUT);
        break;
    case T38_FIELD_HDLC_FCS_OK:
        /* Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_OK messages, in IFP packets with
            incrementing sequence numbers, which are actually repeats. They get through to this point because
            of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */
        if(t->current_rx_data_type != data_type || t->current_rx_field_type != field_type){
            hdlc_accept_frame(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, !fe->rx_data_missing);
        }
        
        fe->hdlc_rx.len = 0;
        fe->rx_data_missing = 0;
        fe->timeout_rx_samples = fe->samples + ms_to_samples(MID_RX_TIMEOUT);
        break;
    case T38_FIELD_HDLC_FCS_BAD:
        /* Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_BAD messages, in IFP packets with
            incrementing sequence numbers, which are actually repeats. They get through to this point because
            of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */
        if(t->current_rx_data_type != data_type || t->current_rx_field_type != field_type){
            hdlc_accept_frame(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, 0);
        }
        
        fe->hdlc_rx.len = 0;
        fe->rx_data_missing = 0;
        fe->timeout_rx_samples = fe->samples + ms_to_samples(MID_RX_TIMEOUT);
        break;
    case T38_FIELD_HDLC_FCS_OK_SIG_END:
        /* Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_OK_SIG_END messages, in IFP packets with
            incrementing sequence numbers, which are actually repeats. They get through to this point because
            of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */
        if(t->current_rx_data_type != data_type || t->current_rx_field_type != field_type){
            hdlc_accept_frame(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, !fe->rx_data_missing);
            hdlc_accept_frame(s, NULL, SIG_STATUS_CARRIER_DOWN, 1);
        }
        
        fe->hdlc_rx.len = 0;
        fe->rx_data_missing = 0;
        /* Treat this like a no signal indicator has occurred, so if the no signal indicator is missing, we are still OK */
        fake_rx_indicator(t, s, T38_IND_NO_SIGNAL);
        break;
    case T38_FIELD_HDLC_FCS_BAD_SIG_END:
        /* Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_BAD_SIG_END messages, in IFP packets with
            incrementing sequence numbers, which are actually repeats. They get through to this point because
            of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */
        if(t->current_rx_data_type != data_type || t->current_rx_field_type != field_type){
            hdlc_accept_frame(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, 0);
            hdlc_accept_frame(s, NULL, SIG_STATUS_CARRIER_DOWN, 1);
        }
        
        fe->hdlc_rx.len = 0;
        fe->rx_data_missing = 0;
        /* Treat this like a no signal indicator has occurred, so if the no signal indicator is missing, we are still OK */
        fake_rx_indicator(t, s, T38_IND_NO_SIGNAL);
        break;
    case T38_FIELD_HDLC_SIG_END:
        /* Some T.38 implementations send multiple T38_FIELD_HDLC_SIG_END messages, in IFP packets with
            incrementing sequence numbers, which are actually repeats. They get through to this point because
            of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */
        if(t->current_rx_data_type != data_type || t->current_rx_field_type != field_type){
            /* WORKAROUND: At least some Mediatrix boxes have a bug, where they can send this message at the
                           end of non-ECM data. We need to tolerate this. We use the generic receive complete
                           indication, rather than the specific HDLC carrier down. */
            /* This message is expected under 2 circumstances. One is as an alternative to T38_FIELD_HDLC_FCS_OK_SIG_END -
               i.e. they send T38_FIELD_HDLC_FCS_OK, and then T38_FIELD_HDLC_SIG_END when the carrier actually drops.
               The other is because the HDLC signal drops unexpectedly - i.e. not just after a final frame. */
            fe->hdlc_rx.len = 0;
            fe->rx_data_missing = 0;
            front_end_status(s, T30_FRONT_END_RECEIVE_COMPLETE);
        }
        
        /* Treat this like a no signal indicator has occurred, so if the no signal indicator is missing, we are still OK */
        fake_rx_indicator(t, s, T38_IND_NO_SIGNAL);
        break;
    case T38_FIELD_T4_NON_ECM_DATA:
        if(!fe->rx_signal_present){
            t30_non_ecm_put_bit(s->t30, SIG_STATUS_TRAINING_SUCCEEDED);
            fe->rx_signal_present = 1;
        }
        
        if(len > 0){
            bit_reverse(buf2, buf, len);
            t30_non_ecm_put_chunk(s->t30, buf2, len);
        }
        
        fe->timeout_rx_samples = fe->samples + ms_to_samples(MID_RX_TIMEOUT);
        break;
    case T38_FIELD_T4_NON_ECM_SIG_END:
        /* Some T.38 implementations send multiple T38_FIELD_T4_NON_ECM_SIG_END messages, in IFP packets with
           incrementing sequence numbers, which are actually repeats. They get through to this point because
           of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */
        if(t->current_rx_data_type != data_type || t->current_rx_field_type != field_type){
            if(len > 0){
                if(!fe->rx_signal_present){
                    t30_non_ecm_put_bit(s->t30, SIG_STATUS_TRAINING_SUCCEEDED);
                    fe->rx_signal_present = 1;
                }
                bit_reverse(buf2, buf, len);
                t30_non_ecm_put_chunk(s->t30, buf2, len);
            }
            front_end_status(s, T30_FRONT_END_RECEIVE_COMPLETE);
        }
        
        fe->rx_signal_present = 0;
        /* Treat this like a no signal indicator has occurred, so if the no signal indicator is missing, we are still OK */
        fake_rx_indicator(t, s, T38_IND_NO_SIGNAL);
        break;
    default:
        break;
    }
    
    return 0;
}



[13:24:38][320]T38_TYPE_OF_MSG_T30_INDICATOR             
[13:24:41][320]T38_TYPE_OF_MSG_T30_INDICATOR  
[13:24:42][320]T38_FIELD_HDLC_DATA
[13:24:42][320]T38_FIELD_HDLC_DATA
[13:24:42][320]T38_FIELD_HDLC_DATA
[13:24:42][320]T38_FIELD_HDLC_DATA
[13:24:42][320]T38_FIELD_HDLC_DATA
[13:24:42][320]T38_FIELD_HDLC_DATA
[13:24:42][320]T38_FIELD_HDLC_DATA
[13:24:42][320]T38_FIELD_HDLC_DATA
[13:24:42][320]T38_FIELD_HDLC_DATA
[13:24:42][320]T38_FIELD_HDLC_DATA
[13:24:42][320]T38_FIELD_HDLC_DATA
[13:24:42][320]T38_FIELD_HDLC_DATA
[13:24:42][320]T38_FIELD_HDLC_DATA
[13:24:42][320]T38_FIELD_HDLC_FCS_OK_SIG_END


lib文件查看

直接用命令dumpbin -exports 你的lib名称
lib /list xx.lib 列出lib里所有obj文件名,我这里如下

找到你关注的obj,这里选择configUL.obj,然后 lib /EXTRACT:lib/config/configUL.obj xx.lib


lib就是obj文件打包起来的,可以用lib.exe解出来,下面是vc环境下的操作,其他环境,看命令行帮助就可以了。

lib /list xx.lib 列出lib里所有obj文件名,我这里如下
。。。。。很多省略
lib/err/err.obj
lib/dict/dictll.obj
lib/coreDump/coreDumpWin32.obj
lib/config/preference.obj
lib/config/configUL.obj

找到你关注的obj,这里选择configUL.obj,然后 lib /EXTRACT:lib/config/configUL.obj xx.lib
解出configUL.obj, 然后把obj拖入IDA,我这里是ida5.5,在函数列表里找你要调用的函数,然后逆之

异常出错在一页发送完成时候

[14:35:01][1820]step1.01
[14:35:01][1820]T38_TYPE_OF_MSG_T30_DATA
[14:35:01][1820]T38_FIELD_HDLC_FCS_OK_SIG_END
[14:35:01][1820]T38_FIELD_HDLC_FCS_OK_SIG_END 1
[14:35:01][1820]t30_hdlc_accept 0
[14:35:01][1820]t30_hdlc_accept 1
[14:35:01][1820]t30_hdlc_accept 2
[14:35:01][1820]t30_hdlc_accept 3
[14:35:01][1820][process_rx_control_msg 2]  state=27
[14:35:01][1820]process_state_iv_pps_q fcf=140
[14:35:01][1820]s->next_tx_step=46
[14:35:01][1820]T30_EOP 0
[14:35:01][1820]T30_EOP 1
[14:35:01][1820]s->operation_in_progress=2
[14:35:01][1820]tiff_close_file 1599ab0
[14:35:01][1820]t->tiff_file=1599be8
[14:35:01][1820]TIFFClose ok
[14:35:01][1820]t->file=C:\ocx\faxsvn\dll\send\temp.tif
[14:35:01][1820]after remove

 




int32_t tiff_close_file(t4_state_t s)
{
    int32_t i;
    tiff_state_t *t;

    t = &s->tiff;
  
    if (t->file)
    {
     
     //  free((uint8_t *) t->file);//memleakwillbe
        t->file = NULL;
        flog("after free");
    }
    flog("tiff_close_file 2");
   return 0;
}



int32_t t4_tx_release(t4_state_t s)
{
    if(s->rx){
        return -1;
    }
    
    if(s->tiff.tiff_file){
        tiff_close_file(s);
    }
    flog("t4_tx_release 0");
    
    free_buffers(s);
    return 0;
}



static int terminate_operation_in_progress(t30_state_t s)
{
 
    switch(s->operation_in_progress)
    {
    case OPERATION_IN_PROGRESS_T4_TX:
         t4_tx_release( s->t4.tx);
        flog("terminate_operation_in_progress 0");

        s->operation_in_progress = OPERATION_IN_PROGRESS_POST_T4_TX;
        break;

}

static void process_state_iv_pps_q(t30_state_t s, const uint8_t *msg, int32_t len)
{
            case T30_EOP:
        
                terminate_operation_in_progress(s);
                flog("T30_EOP 2");
                send_dcn(s);
                break;
}
static void process_rx_control_msg(t30_state_t s, const uint8_t *msg, int32_t len)
{

        case T30_STATE_IV_PPS_Q:
            process_state_iv_pps_q(s, msg, len);
            break;

}
void t30_hdlc_accept(t30_state_t s, const uint8_t* msg, int32_t len, int32_t ok)
{
     
    
    process_rx_control_msg( s, msg, len);
    flog("t30_hdlc_accept 4");
}
static void hdlc_accept_frame(terminal_state_t s, const uint8_t *msg, int32_t len, int32_t ok)
{
    t30_hdlc_accept( s->t30, msg, len, ok);
}
static int32_t process_rx_data(t38_state_t t, void * user_data, int32_t data_type, int32_t field_type, const uint8_t *buf, int32_t len)
{
    terminal_state_t s =(struct terminal_state *) user_data;

    case T38_FIELD_HDLC_FCS_OK_SIG_END:
     
        if(t->current_rx_data_type != data_type || t->current_rx_field_type != field_type){
          
            hdlc_accept_frame( s, fe->hdlc_rx.buf, fe->hdlc_rx.len, !fe->rx_data_missing);
       
            hdlc_accept_frame(s, NULL, SIG_STATUS_CARRIER_DOWN, 1);
        }
}

int32_t t38_core_rx_ifp_packet(void* data, struct frame *f, int32_t total)
{

    t38_state_t s =(t38_state_t) data;


    type = (buf[0] >> 6) & 1;
    ptr = 0;
    switch (type)
    {

    case T38_TYPE_OF_MSG_T30_DATA:
        flog("T38_TYPE_OF_MSG_T30_DATA");
    
            s->ops->data_proc(s, s->rx_data, t30_data, t30_field_type, msg, numocts);
            s->current_rx_data_type = t30_data;
            s->current_rx_field_type = t30_field_type;
        }

}

 

int32_t udptl_recv_proc(void* handle, uint8_t*buf, int32_t len)
{
    struct udptl_struct *s =(struct udptl_struct *) handle;

    len = udptl_rx_packet(s, buf, len);
    if(len < 1){
        return -1;
    }
    flog("step1.01");
    if(s->cb){
        s->cb(s->data, s->f, len);
    }
    
    return 0;
}


int FaxControlProcess::FaxConSend()
{
    terminal_state_t t = NULL;
    struct udptl_io io;
    
    uint8_t buf[2048];
    int len, last_state = 0;

 
    

    if(( t = FaxConInit()) == NULL)
 
    io.send = terminal_send;
    udptl_register(t->t38_fe.t38->hudptl, &io, (void*)fd);
 
    while(1){
     
      
        if(ret > 0 && FD_ISSET(fd, &rdList))
        {
            len = recv(fd, (char *)buf, sizeof(buf), 0);

            if(len > 0){

                udptl_recv_proc(t->t38_fe.t38->hudptl,buf, len);                

            }
        }
        
        terminal_send_timeout(t, tvdiff_us(now, last) * 8 / 1000);
   
        }
        if(last_state == 12)//T30_PHASE_CALL_FINISHED
        {
         
            break;
        }
  
    }
    
    return 0;
}

数据接收流中的接收目录以及文件转换

void * FaxControlProcess::Thread()
{
 
    while (stop == false)
    {
  
            FaxConRecv();
   
           FileConvert(tiffFile,noTiffFile)
         
    
    }
    stop = true;
    flog("FaxControlProcess::Thread leave");

    return NULL;
}


int FaxControlProcess::FaxConRecv()
{
 
   t = FaxConInit()
  
    io.send = terminal_send;
    udptl_register(t->t38_fe.t38->hudptl, &io, (void*)fd);
 
    while(1){     
     
            len = recv(fd, (char *)buf, sizeof(buf), 0);
    
                udptl_recv_proc(t->t38_fe.t38->hudptl, buf, len);
      
        
        terminal_send_timeout(t, tvdiff_us(now, last) * 8 / 1000);
 
        if(last_state == 12)//T30_PHASE_CALL_FINISHED
        {
            SetFaxLastErr(GetFaxt30LastErr(t));
            break;
        }
    }
  
}


terminal_state_t FaxControlProcess::FaxConInit()
{
   
    t = terminal_init(&arg);
  
        t30_set_rx_file(t->t30, (const unsigned char *)(tiffFile.c_str()), -1);
  
}


int FaxControlProcess::StartFax(struct FaxConArg &setFaxPar,const char *sendFile,const char *recvFile)
{
    
    char temp[1024];
    char *cFile = NULL;
    memset(temp, 0, sizeof(temp));
    
        isSend = false;
        cFile = (char *)recvFile;
  
    CreateTiffName(cFile, temp);
 
    noTiffFile = cFile;
    tiffFile = temp;
  
    Start() ;
  
}


int MsgInterface::RecvFax(char* phone,char* faxid)
{
 
 
    int ret = FindFaxSendPacket(phone,faxid,t_packet);
 
    Req_Fax t_req;
 
    t_packet.faxprol = new FaxControlProcess;
  
       
    char recvfile[256];
    memset(recvfile,0,sizeof(recvfile));
    char filename[100];
    memset(filename,0,sizeof(filename));
    GetFileName(filename);
    strcpy(t_packet.path,filename);
    sprintf(recvfile,"%s%s",m_fax_recvpath,filename);
    ret = t_packet.faxprol->StartFax(arg,NULL,recvfile);
 
    ret = UpdateFaxSendPacket(t_packet);
  }

void MsgInterface::GetFileName(char* buff)
{
    SYSTEMTIME lpsystime;  
    GetLocalTime(&lpsystime);  
    sprintf(buff,"%u_%u_%u_%u.pdf",lpsystime.wHour,lpsystime.wMinute,lpsystime.wSecond,lpsystime.wMilliseconds);
    return ;
}

void MsgInterface::SetFaxRecvPath(char* path)
{
  
 
        memset(m_fax_recvpath,0,sizeof(m_fax_recvpath));
 
        sprintf(m_fax_recvpath,"%s",path);
  
     
}


int MainManage::Start()
{
  
    m_recvface->SetMsgInterface(m_msginterface);
    m_radio->SetManage(this);
    ret = m_recvface->StartMsgRecvInterface();
   
    m_send = new MySendThread(*this);
 
    ret = m_send->Start();
 

    m_recv = new MyRecvThread(*this);
 
    ret = m_recv->Start();
 
    char lpPath[200];
    memset(lpPath,0,sizeof(lpPath));
    CString strFullName = AfxGetApp()->m_pszHelpFilePath;
    char drive[MAX_PATH];
    char dir[MAX_PATH];
    _splitpath(strFullName,drive,dir,NULL,NULL);
     _makepath(lpPath,drive,dir,"",NULL);
    SetCommonPath(lpPath);
 
    _makepath(lpPath,drive,dir,"recv\\",NULL);
    SetFaxRecvPath(lpPath);
  
    ret = InitMedia();
 
 
    return 0;
}


bool FaxControlProcess::FileConvert(std::string &inputPath, std::string &outPutPath)
{
   
    CPrinterSettings Seting("SmartPrinter Pro");  // 设置打印机名称
    int iRet;
    bool retBool = false;

    bool m_fApplyPageFlag = false;
    if(m_fApplyPageFlag)   /* 设置页眉 */
    {    
        Seting.SetPageHeader("crong crc616 PageHeader",15,"Tahoma",25,25);
        Seting.SetPageFooter("crong crc616 SetPageFooter",15,"Tahoma",25,25);
    }else
    {
        Seting.SetPageHeader("");
        Seting.SetPageFooter("");
    }

    Seting.SetPrintMaxPage(-1);    // 打印前几页 ? -1: All Page
    Seting.SetPageSize(9) ;       // 标准页面 A4   A4 = 9

    bool bSilent = true;
    CConvertAgent *pConvertEngine = NULL;
    pConvertEngine = new CConvertAgent();

  
    if(pConvertEngine != NULL)
    {
        iRet = pConvertEngine->InitAgent("SmartPrinter Pro", 60, "Demo","Demo"/*,bSilent*/ );
        if(iRet == SM_SUCCESS)   
        {
            iRet = pConvertEngine->ConvertDoc(inputPath.c_str(),outPutPath.c_str());
            retBool = true;
        }
    }

    if(pConvertEngine != NULL)
    {
        delete pConvertEngine;
        pConvertEngine = NULL;
    }
    flog("retBool=%d",retBool);
    return retBool;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值