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 |
00 | data |
ee | data |
a8 | data |
c4 | data |
80 | data |
11 | data |
e7 | data |
b3 | data |
10 | CRC |
03 | CRC |
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;
}