1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909 |
- /*
- * SpanDSP - a series of DSP components for telephony
- *
- * fax_tester.c
- *
- * Written by Steve Underwood <steveu@coppice.org>
- *
- * Copyright (C) 2008 Steve Underwood
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2, as
- * published by the Free Software Foundation.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- /*! \file */
- #if defined(HAVE_CONFIG_H)
- #include "config.h"
- #endif
- #include <inttypes.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #if defined(HAVE_TGMATH_H)
- #include <tgmath.h>
- #endif
- #if defined(HAVE_MATH_H)
- #include <math.h>
- #endif
- #include "floating_fudge.h"
- #include <assert.h>
- #include <fcntl.h>
- #include <time.h>
- #include <unistd.h>
- #if defined(HAVE_LIBXML_XMLMEMORY_H)
- #include <libxml/xmlmemory.h>
- #endif
- #if defined(HAVE_LIBXML_PARSER_H)
- #include <libxml/parser.h>
- #endif
- #if defined(HAVE_LIBXML_XINCLUDE_H)
- #include <libxml/xinclude.h>
- #endif
- #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
- #include "spandsp.h"
- #include "fax_utils.h"
- #include "fax_tester.h"
- #define HDLC_FRAMING_OK_THRESHOLD 5
- extern const char *output_tiff_file_name;
- struct xml_node_parms_s
- {
- xmlChar *dir;
- xmlChar *type;
- xmlChar *modem;
- xmlChar *value;
- xmlChar *tag;
- xmlChar *bad_rows;
- xmlChar *crc_error;
- xmlChar *pattern;
- xmlChar *timein;
- xmlChar *timeout;
- xmlChar *min_bits;
- xmlChar *frame_size;
- xmlChar *block;
- xmlChar *compression;
- };
- struct
- {
- const char *tag;
- int code;
- } t30_status[] =
- {
- {"OK", T30_ERR_OK},
- {"CEDTONE", T30_ERR_CEDTONE},
- {"T0_EXPIRED", T30_ERR_T0_EXPIRED},
- {"T1_EXPIRED", T30_ERR_T1_EXPIRED},
- {"T3_EXPIRED", T30_ERR_T3_EXPIRED},
- {"HDLC_CARRIER", T30_ERR_HDLC_CARRIER},
- {"CANNOT_TRAIN", T30_ERR_CANNOT_TRAIN},
- {"OPER_INT_FAIL", T30_ERR_OPER_INT_FAIL},
- {"INCOMPATIBLE", T30_ERR_INCOMPATIBLE},
- {"RX_INCAPABLE", T30_ERR_RX_INCAPABLE},
- {"TX_INCAPABLE", T30_ERR_TX_INCAPABLE},
- {"NORESSUPPORT", T30_ERR_NORESSUPPORT},
- {"NOSIZESUPPORT", T30_ERR_NOSIZESUPPORT},
- {"UNEXPECTED", T30_ERR_UNEXPECTED},
- {"TX_BADDCS", T30_ERR_TX_BADDCS},
- {"TX_BADPG", T30_ERR_TX_BADPG},
- {"TX_ECMPHD", T30_ERR_TX_ECMPHD},
- {"TX_GOTDCN", T30_ERR_TX_GOTDCN},
- {"TX_INVALRSP", T30_ERR_TX_INVALRSP},
- {"TX_NODIS", T30_ERR_TX_NODIS},
- {"TX_PHBDEAD", T30_ERR_TX_PHBDEAD},
- {"TX_PHDDEAD", T30_ERR_TX_PHDDEAD},
- {"TX_T5EXP", T30_ERR_TX_T5EXP},
- {"RX_ECMPHD", T30_ERR_RX_ECMPHD},
- {"RX_GOTDCS", T30_ERR_RX_GOTDCS},
- {"RX_INVALCMD", T30_ERR_RX_INVALCMD},
- {"RX_NOCARRIER", T30_ERR_RX_NOCARRIER},
- {"RX_NOEOL", T30_ERR_RX_NOEOL},
- {"RX_NOFAX", T30_ERR_RX_NOFAX},
- {"RX_T2EXPDCN", T30_ERR_RX_T2EXPDCN},
- {"RX_T2EXPD", T30_ERR_RX_T2EXPD},
- {"RX_T2EXPFAX", T30_ERR_RX_T2EXPFAX},
- {"RX_T2EXPMPS", T30_ERR_RX_T2EXPMPS},
- {"RX_T2EXPRR", T30_ERR_RX_T2EXPRR},
- {"RX_T2EXP", T30_ERR_RX_T2EXP},
- {"RX_DCNWHY", T30_ERR_RX_DCNWHY},
- {"RX_DCNDATA", T30_ERR_RX_DCNDATA},
- {"RX_DCNFAX", T30_ERR_RX_DCNFAX},
- {"RX_DCNPHD", T30_ERR_RX_DCNPHD},
- {"RX_DCNRRD", T30_ERR_RX_DCNRRD},
- {"RX_DCNNORTN", T30_ERR_RX_DCNNORTN},
- {"FILEERROR", T30_ERR_FILEERROR},
- {"NOPAGE", T30_ERR_NOPAGE},
- {"BADTIFF", T30_ERR_BADTIFF},
- {"BADPAGE", T30_ERR_BADPAGE},
- {"BADTAG", T30_ERR_BADTAG},
- {"BADTIFFHDR", T30_ERR_BADTIFFHDR},
- {"NOMEM", T30_ERR_NOMEM},
- {"RETRYDCN", T30_ERR_RETRYDCN},
- {"CALLDROPPED", T30_ERR_CALLDROPPED},
- {"NOPOLL", T30_ERR_NOPOLL},
- {"IDENT_UNACCEPTABLE", T30_ERR_IDENT_UNACCEPTABLE},
- {"SUB_UNACCEPTABLE", T30_ERR_SUB_UNACCEPTABLE},
- {"SEP_UNACCEPTABLE", T30_ERR_SEP_UNACCEPTABLE},
- {"PSA_UNACCEPTABLE", T30_ERR_PSA_UNACCEPTABLE},
- {"SID_UNACCEPTABLE", T30_ERR_SID_UNACCEPTABLE},
- {"PWD_UNACCEPTABLE", T30_ERR_PWD_UNACCEPTABLE},
- {"TSA_UNACCEPTABLE", T30_ERR_TSA_UNACCEPTABLE},
- {"IRA_UNACCEPTABLE", T30_ERR_IRA_UNACCEPTABLE},
- {"CIA_UNACCEPTABLE", T30_ERR_CIA_UNACCEPTABLE},
- {"ISP_UNACCEPTABLE", T30_ERR_ISP_UNACCEPTABLE},
- {"CSA_UNACCEPTABLE", T30_ERR_CSA_UNACCEPTABLE},
- {NULL, -1}
- };
- static void timer_update(faxtester_state_t *s, int len)
- {
- s->timer += len;
- if (s->timer > s->timeout)
- {
- s->timeout = 0x7FFFFFFFFFFFFFFFLL;
- span_log(&s->logging, SPAN_LOG_FLOW, "FAX tester step timed out\n");
- printf("Test failed\n");
- exit(2);
- }
- }
- /*- End of function --------------------------------------------------------*/
- static void front_end_step_complete(faxtester_state_t *s)
- {
- while (faxtester_next_step(s) == 0)
- ;
- /*endwhile*/
- }
- /*- End of function --------------------------------------------------------*/
- static int faxtester_phase_b_handler(void *user_data, int result)
- {
- int ch;
- int status;
- faxtester_state_t *s;
- const char *u;
- s = (faxtester_state_t *) user_data;
- ch = s->far_tag;
- status = T30_ERR_OK;
- if ((u = t30_get_rx_ident(s->far_t30)))
- {
- printf("%c: Phase B: remote ident '%s'\n", ch, u);
- if (s->expected_rx_info.ident[0] && strcmp(s->expected_rx_info.ident, u))
- {
- printf("%c: Phase B: remote ident incorrect! - expected '%s'\n", ch, s->expected_rx_info.ident);
- status = T30_ERR_IDENT_UNACCEPTABLE;
- }
- }
- else
- {
- if (s->expected_rx_info.ident[0])
- {
- printf("%c: Phase B: remote ident missing!\n", ch);
- status = T30_ERR_IDENT_UNACCEPTABLE;
- }
- }
- if ((u = t30_get_rx_sub_address(s->far_t30)))
- {
- printf("%c: Phase B: remote sub-address '%s'\n", ch, u);
- if (s->expected_rx_info.sub_address[0] && strcmp(s->expected_rx_info.sub_address, u))
- {
- printf("%c: Phase B: remote sub-address incorrect! - expected '%s'\n", ch, s->expected_rx_info.sub_address);
- status = T30_ERR_SUB_UNACCEPTABLE;
- }
- }
- else
- {
- if (s->expected_rx_info.sub_address[0])
- {
- printf("%c: Phase B: remote sub-address missing!\n", ch);
- status = T30_ERR_SUB_UNACCEPTABLE;
- }
- }
- if ((u = t30_get_rx_polled_sub_address(s->far_t30)))
- {
- printf("%c: Phase B: remote polled sub-address '%s'\n", ch, u);
- if (s->expected_rx_info.polled_sub_address[0] && strcmp(s->expected_rx_info.polled_sub_address, u))
- {
- printf("%c: Phase B: remote polled sub-address incorrect! - expected '%s'\n", ch, s->expected_rx_info.polled_sub_address);
- status = T30_ERR_PSA_UNACCEPTABLE;
- }
- }
- else
- {
- if (s->expected_rx_info.polled_sub_address[0])
- {
- printf("%c: Phase B: remote polled sub-address missing!\n", ch);
- status = T30_ERR_PSA_UNACCEPTABLE;
- }
- }
- if ((u = t30_get_rx_selective_polling_address(s->far_t30)))
- {
- printf("%c: Phase B: remote selective polling address '%s'\n", ch, u);
- if (s->expected_rx_info.selective_polling_address[0] && strcmp(s->expected_rx_info.selective_polling_address, u))
- {
- printf("%c: Phase B: remote selective polling address incorrect! - expected '%s'\n", ch, s->expected_rx_info.selective_polling_address);
- status = T30_ERR_SEP_UNACCEPTABLE;
- }
- }
- else
- {
- if (s->expected_rx_info.selective_polling_address[0])
- {
- printf("%c: Phase B: remote selective polling address missing!\n", ch);
- status = T30_ERR_SEP_UNACCEPTABLE;
- }
- }
- if ((u = t30_get_rx_sender_ident(s->far_t30)))
- {
- printf("%c: Phase B: remote sender ident '%s'\n", ch, u);
- if (s->expected_rx_info.sender_ident[0] && strcmp(s->expected_rx_info.sender_ident, u))
- {
- printf("%c: Phase B: remote sender ident incorrect! - expected '%s'\n", ch, s->expected_rx_info.sender_ident);
- status = T30_ERR_SID_UNACCEPTABLE;
- }
- }
- else
- {
- if (s->expected_rx_info.sender_ident[0])
- {
- printf("%c: Phase B: remote sender ident missing!\n", ch);
- status = T30_ERR_SID_UNACCEPTABLE;
- }
- }
- if ((u = t30_get_rx_password(s->far_t30)))
- {
- printf("%c: Phase B: remote password '%s'\n", ch, u);
- if (s->expected_rx_info.password[0] && strcmp(s->expected_rx_info.password, u))
- {
- printf("%c: Phase B: remote password incorrect! - expected '%s'\n", ch, s->expected_rx_info.password);
- status = T30_ERR_PWD_UNACCEPTABLE;
- }
- }
- else
- {
- if (s->expected_rx_info.password[0])
- {
- printf("%c: Phase B: remote password missing!\n", ch);
- status = T30_ERR_PWD_UNACCEPTABLE;
- }
- }
- printf("%c: Phase B handler on channel %c - (0x%X) %s\n", ch, ch, result, t30_frametype(result));
- return status;
- }
- /*- End of function --------------------------------------------------------*/
- static int faxtester_phase_d_handler(void *user_data, int result)
- {
- int i;
- int ch;
- faxtester_state_t *s;
- char tag[20];
- s = (faxtester_state_t *) user_data;
- ch = s->far_tag;
- i = 0;
- snprintf(tag, sizeof(tag), "%c: Phase D", ch);
- printf("%c: Phase D handler on channel %c - (0x%X) %s\n", ch, ch, result, t30_frametype(result));
- fax_log_page_transfer_statistics(s->far_t30, tag);
- fax_log_tx_parameters(s->far_t30, tag);
- fax_log_rx_parameters(s->far_t30, tag);
- if (s->use_receiver_not_ready)
- t30_set_receiver_not_ready(s->far_t30, 3);
- if (s->test_local_interrupt)
- {
- if (i == 0)
- {
- printf("%c: Initiating interrupt request\n", ch);
- t30_local_interrupt_request(s->far_t30, true);
- }
- else
- {
- switch (result)
- {
- case T30_PIP:
- case T30_PRI_MPS:
- case T30_PRI_EOM:
- case T30_PRI_EOP:
- printf("%c: Accepting interrupt request\n", ch);
- t30_local_interrupt_request(s->far_t30, true);
- break;
- case T30_PIN:
- break;
- }
- }
- }
- return T30_ERR_OK;
- }
- /*- End of function --------------------------------------------------------*/
- static void faxtester_phase_e_handler(void *user_data, int result)
- {
- int ch;
- faxtester_state_t *s;
- char tag[20];
- s = (faxtester_state_t *) user_data;
- ch = s->far_tag;
- snprintf(tag, sizeof(tag), "%c: Phase E", ch);
- printf("%c: Phase E handler on channel %c - (%d) %s\n", ch, ch, result, t30_completion_code_to_str(result));
- fax_log_final_transfer_statistics(s->far_t30, tag);
- fax_log_tx_parameters(s->far_t30, tag);
- fax_log_rx_parameters(s->far_t30, tag);
- }
- /*- End of function --------------------------------------------------------*/
- static void t30_real_time_frame_handler(void *user_data,
- bool incoming,
- const uint8_t *msg,
- int len)
- {
- if (msg == NULL)
- {
- }
- else
- {
- fprintf(stderr,
- "T.30: Real time frame handler - %s, %s, length = %d\n",
- (incoming) ? "line->T.30" : "T.30->line",
- t30_frametype(msg[2]),
- len);
- }
- }
- /*- End of function --------------------------------------------------------*/
- static int faxtester_document_handler(void *user_data, int event)
- {
- int ch;
- faxtester_state_t *s;
- t30_state_t *t;
- s = (faxtester_state_t *) user_data;
- ch = s->far_tag;
- t = s->far_t30;
- fprintf(stderr, "%c: Document handler on channel %c - event %d\n", ch, ch, event);
- if (s->next_tx_file[0])
- {
- t30_set_tx_file(t, s->next_tx_file, -1, -1);
- s->next_tx_file[0] = '\0';
- return true;
- }
- return false;
- }
- /*- End of function --------------------------------------------------------*/
- static void faxtester_real_time_frame_handler(faxtester_state_t *s,
- int direction,
- const uint8_t *msg,
- int len)
- {
- if (msg == NULL)
- {
- while (faxtester_next_step(s) == 0)
- ;
- /*endwhile*/
- }
- else
- {
- fprintf(stderr,
- "TST: Real time frame handler - %s, %s, length = %d\n",
- (direction) ? "line->tester" : "tester->line",
- t30_frametype(msg[2]),
- len);
- if (direction && msg[1] == s->awaited[1])
- {
- if ((s->awaited_len >= 0 && len != abs(s->awaited_len))
- ||
- (s->awaited_len < 0 && len < abs(s->awaited_len))
- ||
- memcmp(msg, s->awaited, abs(s->awaited_len)) != 0)
- {
- span_log_buf(&s->logging, SPAN_LOG_FLOW, "Expected", s->awaited, abs(s->awaited_len));
- span_log_buf(&s->logging, SPAN_LOG_FLOW, "Received", msg, len);
- printf("Test failed\n");
- exit(2);
- }
- }
- if (msg[1] == s->awaited[1])
- {
- while (faxtester_next_step(s) == 0)
- ;
- /*endwhile*/
- }
- }
- }
- /*- End of function --------------------------------------------------------*/
- void faxtester_send_hdlc_flags(faxtester_state_t *s, int flags)
- {
- hdlc_tx_flags(&s->modems.hdlc_tx, flags);
- }
- /*- End of function --------------------------------------------------------*/
- void faxtester_send_hdlc_msg(faxtester_state_t *s, const uint8_t *msg, int len, int crc_ok)
- {
- hdlc_tx_frame(&s->modems.hdlc_tx, msg, len);
- if (!crc_ok)
- hdlc_tx_corrupt_frame(&s->modems.hdlc_tx);
- }
- /*- End of function --------------------------------------------------------*/
- static void hdlc_underflow_handler(void *user_data)
- {
- faxtester_state_t *s;
- uint8_t buf[400];
- s = (faxtester_state_t *) user_data;
- if (s->image_buffer)
- {
- /* We are sending an ECM image */
- if (s->image_ptr < s->image_len)
- {
- buf[0] = 0xFF;
- buf[1] = 0x03;
- buf[2] = 0x06;
- buf[3] = s->image_ptr/s->ecm_frame_size;
- memcpy(&buf[4], &s->image_buffer[s->image_ptr], s->ecm_frame_size);
- hdlc_tx_frame(&s->modems.hdlc_tx, buf, 4 + s->ecm_frame_size);
- if (s->corrupt_crc >= 0 && s->corrupt_crc == s->image_ptr/s->ecm_frame_size)
- hdlc_tx_corrupt_frame(&s->modems.hdlc_tx);
- s->image_ptr += s->ecm_frame_size;
- return;
- }
- /* The actual image is over. We are sending the final RCP frames. */
- if (s->image_bit_ptr > 2)
- {
- s->image_bit_ptr--;
- buf[0] = 0xFF;
- buf[1] = 0x03;
- buf[2] = 0x86;
- hdlc_tx_frame(&s->modems.hdlc_tx, buf, 3);
- return;
- }
- /* All done. */
- s->image_buffer = NULL;
- }
- front_end_step_complete(s);
- }
- /*- End of function --------------------------------------------------------*/
- static void modem_tx_status(void *user_data, int status)
- {
- faxtester_state_t *s;
- s = (faxtester_state_t *) user_data;
- printf("Tx status is %s (%d)\n", signal_status_to_str(status), status);
- switch (status)
- {
- case SIG_STATUS_SHUTDOWN_COMPLETE:
- front_end_step_complete(s);
- break;
- }
- }
- /*- End of function --------------------------------------------------------*/
- static void tone_detected(void *user_data, int tone, int level, int delay)
- {
- faxtester_state_t *s;
- s = (faxtester_state_t *) user_data;
- span_log(&s->logging,
- SPAN_LOG_FLOW,
- "%s (%d) declared (%ddBm0)\n",
- modem_connect_tone_to_str(tone),
- tone,
- level);
- if (tone != MODEM_CONNECT_TONES_NONE)
- {
- s->tone_on_time = s->timer;
- }
- else
- {
- span_log(&s->logging,
- SPAN_LOG_FLOW,
- "Tone was on for %fs\n",
- (float) (s->timer - s->tone_on_time)/SAMPLE_RATE + 0.55);
- }
- s->tone_state = tone;
- if (tone == MODEM_CONNECT_TONES_NONE)
- front_end_step_complete(s);
- }
- /*- End of function --------------------------------------------------------*/
- static int non_ecm_get_bit(void *user_data)
- {
- faxtester_state_t *s;
- int bit;
- s = (faxtester_state_t *) user_data;
- if (s->image_bit_ptr == 0)
- {
- if (s->image_ptr >= s->image_len)
- {
- s->image_buffer = NULL;
- return SIG_STATUS_END_OF_DATA;
- }
- s->image_bit_ptr = 8;
- s->image_ptr++;
- }
- s->image_bit_ptr--;
- bit = (s->image_buffer[s->image_ptr] >> (7 - s->image_bit_ptr)) & 0x01;
- //printf("Rx bit - %d\n", bit);
- return bit;
- }
- /*- End of function --------------------------------------------------------*/
- static void faxtester_set_ecm_image_buffer(faxtester_state_t *s, int block, int frame_size, int crc_hit)
- {
- s->image_ptr = 256*frame_size*block;
- if (s->image_len > s->image_ptr + 256*frame_size)
- s->image_len = s->image_ptr + 256*frame_size;
- s->ecm_frame_size = frame_size;
- s->image_bit_ptr = 8;
- s->corrupt_crc = crc_hit;
- s->image_buffer = s->image;
- /* Send the first frame */
- hdlc_underflow_handler(s);
- }
- /*- End of function --------------------------------------------------------*/
- static void non_ecm_rx_status(void *user_data, int status)
- {
- faxtester_state_t *s;
- s = (faxtester_state_t *) user_data;
- span_log(&s->logging, SPAN_LOG_FLOW, "Non-ECM carrier status is %s (%d)\n", signal_status_to_str(status), status);
- switch (status)
- {
- case SIG_STATUS_TRAINING_FAILED:
- s->modems.rx_trained = false;
- break;
- case SIG_STATUS_TRAINING_SUCCEEDED:
- /* The modem is now trained */
- s->modems.rx_trained = true;
- break;
- case SIG_STATUS_CARRIER_UP:
- s->modems.rx_signal_present = true;
- break;
- case SIG_STATUS_CARRIER_DOWN:
- if (s->modems.rx_trained)
- faxtester_real_time_frame_handler(s, true, NULL, 0);
- s->modems.rx_signal_present = false;
- s->modems.rx_trained = false;
- break;
- }
- }
- /*- End of function --------------------------------------------------------*/
- static void non_ecm_put_bit(void *user_data, int bit)
- {
- if (bit < 0)
- {
- non_ecm_rx_status(user_data, bit);
- return;
- }
- }
- /*- End of function --------------------------------------------------------*/
- static void hdlc_rx_status(void *user_data, int status)
- {
- faxtester_state_t *s;
- s = (faxtester_state_t *) user_data;
- span_log(&s->logging, SPAN_LOG_FLOW, "HDLC carrier status is %s (%d)\n", signal_status_to_str(status), status);
- switch (status)
- {
- case SIG_STATUS_TRAINING_FAILED:
- s->modems.rx_trained = false;
- break;
- case SIG_STATUS_TRAINING_SUCCEEDED:
- /* The modem is now trained */
- s->modems.rx_trained = true;
- break;
- case SIG_STATUS_CARRIER_UP:
- s->modems.rx_signal_present = true;
- break;
- case SIG_STATUS_CARRIER_DOWN:
- s->modems.rx_signal_present = false;
- s->modems.rx_trained = false;
- break;
- }
- }
- /*- End of function --------------------------------------------------------*/
- static void hdlc_accept(void *user_data, const uint8_t *msg, int len, int ok)
- {
- faxtester_state_t *s;
- if (len < 0)
- {
- hdlc_rx_status(user_data, len);
- return;
- }
- s = (faxtester_state_t *) user_data;
- faxtester_real_time_frame_handler(s, true, msg, len);
- }
- /*- End of function --------------------------------------------------------*/
- int faxtester_rx(faxtester_state_t *s, int16_t *amp, int len)
- {
- int i;
- for (i = 0; i < len; i++)
- amp[i] = dc_restore(&s->modems.dc_restore, amp[i]);
- if (s->modems.rx_handler)
- s->modems.rx_handler(s->modems.rx_user_data, amp, len);
- timer_update(s, len);
- if (s->wait_for_silence)
- {
- if (!s->modems.rx_signal_present)
- {
- s->wait_for_silence = false;
- front_end_step_complete(s);
- }
- }
- return 0;
- }
- /*- End of function --------------------------------------------------------*/
- int faxtester_tx(faxtester_state_t *s, int16_t *amp, int max_len)
- {
- int len;
- len = 0;
- if (s->transmit)
- {
- while ((len += s->modems.tx_handler(s->modems.tx_user_data, amp + len, max_len - len)) < max_len)
- {
- /* Allow for a change of tx handler within a block */
- front_end_step_complete(s);
- if (!s->transmit)
- {
- if (s->modems.transmit_on_idle)
- {
- /* Pad to the requested length with silence */
- memset(amp + len, 0, (max_len - len)*sizeof(int16_t));
- len = max_len;
- }
- break;
- }
- }
- }
- else
- {
- if (s->modems.transmit_on_idle)
- {
- /* Pad to the requested length with silence */
- memset(amp, 0, max_len*sizeof(int16_t));
- len = max_len;
- }
- }
- return len;
- }
- /*- End of function --------------------------------------------------------*/
- void faxtest_set_rx_silence(faxtester_state_t *s)
- {
- s->wait_for_silence = true;
- }
- /*- End of function --------------------------------------------------------*/
- void faxtester_set_rx_type(void *user_data, int type, int bit_rate, int short_train, int use_hdlc)
- {
- faxtester_state_t *s;
- fax_modems_state_t *t;
- s = (faxtester_state_t *) user_data;
- t = &s->modems;
- span_log(&s->logging, SPAN_LOG_FLOW, "Set rx type %d\n", type);
- if (s->current_rx_type == type)
- return;
- s->current_rx_type = type;
- if (use_hdlc)
- hdlc_rx_init(&t->hdlc_rx, false, false, HDLC_FRAMING_OK_THRESHOLD, hdlc_accept, s);
- switch (type)
- {
- case T30_MODEM_CED:
- fax_modems_start_slow_modem(t, FAX_MODEM_CED_TONE_RX);
- s->tone_state = MODEM_CONNECT_TONES_NONE;
- break;
- case T30_MODEM_CNG:
- fax_modems_start_slow_modem(t, FAX_MODEM_CNG_TONE_RX);
- s->tone_state = MODEM_CONNECT_TONES_NONE;
- break;
- case T30_MODEM_V21:
- if (s->flush_handler)
- s->flush_handler(s, s->flush_user_data, 3);
- fax_modems_start_slow_modem(t, FAX_MODEM_V21_RX);
- break;
- case T30_MODEM_V27TER:
- fax_modems_start_fast_modem(t, FAX_MODEM_V27TER_RX, bit_rate, short_train, use_hdlc);
- break;
- case T30_MODEM_V29:
- fax_modems_start_fast_modem(t, FAX_MODEM_V29_RX, bit_rate, short_train, use_hdlc);
- break;
- case T30_MODEM_V17:
- fax_modems_start_fast_modem(t, FAX_MODEM_V17_RX, bit_rate, short_train, use_hdlc);
- break;
- case T30_MODEM_DONE:
- span_log(&s->logging, SPAN_LOG_FLOW, "FAX exchange complete\n");
- default:
- fax_modems_set_rx_handler(t, (span_rx_handler_t) &span_dummy_rx, s, NULL, s);
- break;
- }
- }
- /*- End of function --------------------------------------------------------*/
- void faxtester_set_tx_type(void *user_data, int type, int bit_rate, int short_train, int use_hdlc)
- {
- faxtester_state_t *s;
- get_bit_func_t get_bit_func;
- void *get_bit_user_data;
- fax_modems_state_t *t;
- int tone;
- s = (faxtester_state_t *) user_data;
- t = &s->modems;
- span_log(&s->logging, SPAN_LOG_FLOW, "Set tx type %d\n", type);
- if (use_hdlc)
- {
- get_bit_func = (get_bit_func_t) hdlc_tx_get_bit;
- get_bit_user_data = (void *) &t->hdlc_tx;
- }
- else
- {
- get_bit_func = non_ecm_get_bit;
- get_bit_user_data = (void *) s;
- }
- if (type == s->current_tx_type)
- {
- if (type == T30_MODEM_PAUSE)
- silence_gen_alter(&t->silence_gen, ms_to_samples(short_train));
- return;
- }
- switch (type)
- {
- case T30_MODEM_PAUSE:
- silence_gen_alter(&t->silence_gen, ms_to_samples(short_train));
- fax_modems_set_tx_handler(t, (span_tx_handler_t) &silence_gen, &t->silence_gen);
- s->transmit = true;
- break;
- case T30_MODEM_CED:
- case T30_MODEM_CNG:
- tone = (type == T30_MODEM_CED) ? FAX_MODEM_CED_TONE_TX : FAX_MODEM_CNG_TONE_TX;
- fax_modems_start_slow_modem(t, tone);
- s->transmit = true;
- break;
- case T30_MODEM_V21:
- fax_modems_start_slow_modem(t, FAX_MODEM_V21_TX);
- fsk_tx_set_modem_status_handler(&t->v21_tx, modem_tx_status, (void *) s);
- s->transmit = true;
- break;
- case T30_MODEM_V27TER:
- fax_modems_set_get_bit(t, get_bit_func, get_bit_user_data);
- fax_modems_start_fast_modem(t, FAX_MODEM_V27TER_TX, bit_rate, short_train, use_hdlc);
- v27ter_tx_set_modem_status_handler(&t->fast_modems.v27ter_tx, modem_tx_status, (void *) s);
- /* For any fast modem, set 200ms of preamble flags */
- hdlc_tx_flags(&t->hdlc_tx, bit_rate/(8*5));
- s->transmit = true;
- break;
- case T30_MODEM_V29:
- fax_modems_set_get_bit(t, get_bit_func, get_bit_user_data);
- fax_modems_start_fast_modem(t, FAX_MODEM_V29_TX, bit_rate, short_train, use_hdlc);
- v29_tx_set_modem_status_handler(&t->fast_modems.v29_tx, modem_tx_status, (void *) s);
- /* For any fast modem, set 200ms of preamble flags */
- hdlc_tx_flags(&t->hdlc_tx, bit_rate/(8*5));
- s->transmit = true;
- break;
- case T30_MODEM_V17:
- fax_modems_set_get_bit(t, get_bit_func, get_bit_user_data);
- fax_modems_start_fast_modem(t, FAX_MODEM_V17_TX, bit_rate, short_train, use_hdlc);
- v17_tx_set_modem_status_handler(&t->fast_modems.v17_tx, modem_tx_status, (void *) s);
- /* For any fast modem, set 200ms of preamble flags */
- hdlc_tx_flags(&t->hdlc_tx, bit_rate/(8*5));
- s->transmit = true;
- break;
- case T30_MODEM_DONE:
- span_log(&s->logging, SPAN_LOG_FLOW, "FAX exchange complete\n");
- /* Fall through */
- default:
- silence_gen_alter(&t->silence_gen, 0);
- fax_modems_set_tx_handler(t, (span_tx_handler_t) &silence_gen, &t->silence_gen);
- s->transmit = false;
- break;
- }
- s->current_tx_type = type;
- }
- /*- End of function --------------------------------------------------------*/
- void faxtester_set_timeout(faxtester_state_t *s, int timeout)
- {
- if (timeout >= 0)
- s->timeout = s->timer + timeout*SAMPLE_RATE/1000;
- else
- s->timeout = 0x7FFFFFFFFFFFFFFFLL;
- }
- /*- End of function --------------------------------------------------------*/
- void faxtester_set_transmit_on_idle(faxtester_state_t *s, int transmit_on_idle)
- {
- s->modems.transmit_on_idle = transmit_on_idle;
- }
- /*- End of function --------------------------------------------------------*/
- void faxtester_set_tep_mode(faxtester_state_t *s, int use_tep)
- {
- fax_modems_set_tep_mode(&s->modems, use_tep);
- }
- /*- End of function --------------------------------------------------------*/
- static void corrupt_image(faxtester_state_t *s, const char *bad_rows)
- {
- int i;
- int j;
- int k;
- uint32_t bits;
- uint32_t bitsx;
- int list[1000];
- int x;
- int row;
- const char *t;
- /* Form the list of rows to be hit */
- x = 0;
- t = bad_rows;
- while (*t)
- {
- while (isspace((int) *t))
- t++;
- if (sscanf(t, "%d", &list[x]) < 1)
- break;
- x++;
- while (isdigit((int) *t))
- t++;
- if (*t == ',')
- t++;
- }
- /* Go through the image, and corrupt the first bit of every listed row */
- bits = 0x7FF;
- bitsx = 0x7FF;
- row = 0;
- for (i = 0; i < s->image_len; i++)
- {
- bits ^= (s->image[i] << 11);
- bitsx ^= (s->image[i] << 11);
- for (j = 0; j < 8; j++)
- {
- if ((bits & 0xFFF) == 0x800)
- {
- /* We are at an EOL. Is this row in the list of rows to be corrupted? */
- row++;
- for (k = 0; k < x; k++)
- {
- if (list[k] == row)
- {
- /* Corrupt this row. TSB85 says to hit the first bit after the EOL */
- bitsx ^= 0x1000;
- }
- }
- }
- bits >>= 1;
- bitsx >>= 1;
- }
- s->image[i] = (bitsx >> 3) & 0xFF;
- }
- span_log(&s->logging, SPAN_LOG_FLOW, "%d rows found. %d corrupted\n", row, x);
- }
- /*- End of function --------------------------------------------------------*/
- static int string_to_msg(uint8_t msg[], uint8_t mask[], const char buf[])
- {
- int i;
- int x;
- const char *t;
- msg[0] = 0;
- mask[0] = 0xFF;
- i = 0;
- t = (char *) buf;
- while (*t)
- {
- /* Skip white space */
- while (isspace((int) *t))
- t++;
- /* If we find ... we allow arbitrary additional info beyond this point in the message */
- if (t[0] == '.' && t[1] == '.' && t[2] == '.')
- {
- return -i;
- }
- else if (isxdigit((int) *t))
- {
- for ( ; isxdigit((int) *t); t++)
- {
- x = *t;
- if (x >= 'a')
- x -= 0x20;
- if (x >= 'A')
- x -= ('A' - 10);
- else
- x -= '0';
- msg[i] = (msg[i] << 4) | x;
- }
- mask[i] = 0xFF;
- if (*t == '/')
- {
- /* There is a mask following the byte */
- mask[i] = 0;
- for (t++; isxdigit((int) *t); t++)
- {
- x = *t;
- if (x >= 'a')
- x -= 0x20;
- if (x >= 'A')
- x -= ('A' - 10);
- else
- x -= '0';
- mask[i] = (mask[i] << 4) | x;
- }
- }
- if (*t && !isspace((int) *t))
- {
- /* Bad string */
- return 0;
- }
- i++;
- }
- }
- return i;
- }
- /*- End of function --------------------------------------------------------*/
- void faxtester_set_flush_handler(faxtester_state_t *s, faxtester_flush_handler_t handler, void *user_data)
- {
- s->flush_handler = handler;
- s->flush_user_data = user_data;
- }
- /*- End of function --------------------------------------------------------*/
- static void fax_prepare(faxtester_state_t *s)
- {
- if (s->far_fax)
- {
- fax_set_transmit_on_idle(s->far_fax, true);
- fax_set_tep_mode(s->far_fax, true);
- }
- #if 0
- t30_set_tx_ident(s->far_t30, "1234567890");
- t30_set_tx_sub_address(s->far_t30, "Sub-address");
- t30_set_tx_sender_ident(s->far_t30, "Sender ID");
- t30_set_tx_password(s->far_t30, "Password");
- t30_set_tx_polled_sub_address(s->far_t30, "Polled sub-address");
- t30_set_tx_selective_polling_address(s->far_t30, "Sel polling address");
- #endif
- t30_set_tx_nsf(s->far_t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp NSF\x00", 16);
- //t30_set_tx_nss(s->far_t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp NSS\x00", 16);
- t30_set_tx_nsc(s->far_t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp NSC\x00", 16);
- t30_set_ecm_capability(s->far_t30, true);
- t30_set_supported_t30_features(s->far_t30,
- T30_SUPPORT_IDENTIFICATION
- | T30_SUPPORT_SELECTIVE_POLLING
- | T30_SUPPORT_SUB_ADDRESSING);
- t30_set_supported_image_sizes(s->far_t30,
- T4_SUPPORT_WIDTH_215MM
- | T4_SUPPORT_WIDTH_255MM
- | T4_SUPPORT_WIDTH_303MM
- | T4_SUPPORT_LENGTH_US_LETTER
- | T4_SUPPORT_LENGTH_US_LEGAL
- | T4_SUPPORT_LENGTH_UNLIMITED);
- t30_set_supported_bilevel_resolutions(s->far_t30,
- T4_RESOLUTION_R8_STANDARD
- | T4_RESOLUTION_R8_FINE
- | T4_RESOLUTION_R8_SUPERFINE
- | T4_RESOLUTION_R16_SUPERFINE
- | T4_RESOLUTION_100_100
- | T4_RESOLUTION_200_100
- | T4_RESOLUTION_200_200
- | T4_RESOLUTION_200_400
- | T4_RESOLUTION_300_300
- | T4_RESOLUTION_300_600
- | T4_RESOLUTION_400_400
- | T4_RESOLUTION_400_800
- | T4_RESOLUTION_600_600
- | T4_RESOLUTION_600_1200
- | T4_RESOLUTION_1200_1200);
- t30_set_supported_colour_resolutions(s->far_t30, 0);
- t30_set_supported_modems(s->far_t30, T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17);
- t30_set_supported_compressions(s->far_t30, T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6);
- t30_set_phase_b_handler(s->far_t30, faxtester_phase_b_handler, (void *) s);
- t30_set_phase_d_handler(s->far_t30, faxtester_phase_d_handler, (void *) s);
- t30_set_phase_e_handler(s->far_t30, faxtester_phase_e_handler, (void *) s);
- t30_set_real_time_frame_handler(s->far_t30, t30_real_time_frame_handler, (void *) s);
- t30_set_document_handler(s->far_t30, faxtester_document_handler, (void *) s);
- }
- /*- End of function --------------------------------------------------------*/
- static void get_node_parms(struct xml_node_parms_s *parms, xmlNodePtr node)
- {
- parms->dir = xmlGetProp(node, (const xmlChar *) "dir");
- parms->type = xmlGetProp(node, (const xmlChar *) "type");
- parms->modem = xmlGetProp(node, (const xmlChar *) "modem");
- parms->value = xmlGetProp(node, (const xmlChar *) "value");
- parms->tag = xmlGetProp(node, (const xmlChar *) "tag");
- parms->bad_rows = xmlGetProp(node, (const xmlChar *) "bad_rows");
- parms->crc_error = xmlGetProp(node, (const xmlChar *) "crc_error");
- parms->pattern = xmlGetProp(node, (const xmlChar *) "pattern");
- parms->timein = xmlGetProp(node, (const xmlChar *) "timein");
- parms->timeout = xmlGetProp(node, (const xmlChar *) "timeout");
- parms->min_bits = xmlGetProp(node, (const xmlChar *) "min_bits");
- parms->frame_size = xmlGetProp(node, (const xmlChar *) "frame_size");
- parms->block = xmlGetProp(node, (const xmlChar *) "block");
- parms->compression = xmlGetProp(node, (const xmlChar *) "compression");
- }
- /*- End of function --------------------------------------------------------*/
- static void free_node_parms(struct xml_node_parms_s *parms)
- {
- if (parms->dir)
- xmlFree(parms->dir);
- if (parms->type)
- xmlFree(parms->type);
- if (parms->modem)
- xmlFree(parms->modem);
- if (parms->value)
- xmlFree(parms->value);
- if (parms->tag)
- xmlFree(parms->tag);
- if (parms->bad_rows)
- xmlFree(parms->bad_rows);
- if (parms->crc_error)
- xmlFree(parms->crc_error);
- if (parms->pattern)
- xmlFree(parms->pattern);
- if (parms->timein)
- xmlFree(parms->timein);
- if (parms->timeout)
- xmlFree(parms->timeout);
- if (parms->min_bits)
- xmlFree(parms->min_bits);
- if (parms->frame_size)
- xmlFree(parms->frame_size);
- if (parms->block)
- xmlFree(parms->block);
- if (parms->compression)
- xmlFree(parms->compression);
- }
- /*- End of function --------------------------------------------------------*/
- SPAN_DECLARE(int) faxtester_next_step(faxtester_state_t *s)
- {
- int delay;
- int flags;
- struct xml_node_parms_s parms;
- uint8_t buf[1000];
- uint8_t mask[1000];
- char path[1024];
- int i;
- int j;
- int hdlc;
- int short_train;
- int min_row_bits;
- int ecm_frame_size;
- int ecm_block;
- int compression_type;
- xmlChar *min;
- xmlChar *max;
- t4_tx_state_t t4_tx_state;
- t30_stats_t t30_stats;
- s->test_for_call_clear = false;
- if (s->cur == NULL)
- {
- if (!s->final_delayed)
- {
- /* Add a bit of waiting at the end, to ensure everything gets flushed through,
- any timers can expire, etc. */
- faxtester_set_timeout(s, -1);
- faxtester_set_rx_type(s, T30_MODEM_NONE, 0, false, false);
- faxtester_set_tx_type(s, T30_MODEM_PAUSE, 0, 120000, false);
- s->final_delayed = true;
- return 1;
- }
- /* Finished */
- printf("Test passed\n");
- exit(0);
- }
- for (;;)
- {
- if (s->cur == NULL)
- {
- if (s->repeat_parent == NULL)
- {
- /* Finished */
- printf("Test passed\n");
- exit(0);
- }
- if (++s->repeat_count > s->repeat_max)
- {
- /* Finished */
- printf("Too many repeats\n");
- printf("Test failed\n");
- exit(0);
- }
- if (s->repeat_count < s->repeat_min)
- {
- s->cur = s->repeat_start;
- }
- else
- {
- s->cur = s->repeat_parent->next;
- s->repeat_parent = NULL;
- }
- }
- if (xmlStrcmp(s->cur->name, (const xmlChar *) "step") == 0)
- {
- break;
- }
- if (s->repeat_parent == NULL && xmlStrcmp(s->cur->name, (const xmlChar *) "repeat") == 0)
- {
- min = xmlGetProp(s->cur, (const xmlChar *) "min");
- max = xmlGetProp(s->cur, (const xmlChar *) "max");
- s->repeat_min = min ? atoi((const char *) min) : 0;
- s->repeat_max = max ? atoi((const char *) max) : INT_MAX;
- s->repeat_count = 0;
- if (min)
- xmlFree(min);
- if (max)
- xmlFree(max);
- if (s->repeat_min > 0)
- {
- s->repeat_parent = s->cur;
- s->repeat_start =
- s->cur = s->cur->xmlChildrenNode;
- continue;
- }
- }
- s->cur = s->cur->next;
- }
- get_node_parms(&parms, s->cur);
- s->cur = s->cur->next;
- span_log(&s->logging,
- SPAN_LOG_FLOW,
- "Dir - %s, type - %s, modem - %s, value - %s, timein - %s, timeout - %s, tag - %s\n",
- (parms.dir) ? (const char *) parms.dir : " ",
- (parms.type) ? (const char *) parms.type : "",
- (parms.modem) ? (const char *) parms.modem : "",
- (parms.value) ? (const char *) parms.value : "",
- (parms.timein) ? (const char *) parms.timein : "",
- (parms.timeout) ? (const char *) parms.timeout : "",
- (parms.tag) ? (const char *) parms.tag : "");
- if (parms.type == NULL)
- {
- free_node_parms(&parms);
- return 1;
- }
- s->timein_x = (parms.timein) ? atoi((const char *) parms.timein) : -1;
- s->timeout_x = (parms.timeout) ? atoi((const char *) parms.timeout) : -1;
- if (parms.dir && strcasecmp((const char *) parms.dir, "R") == 0)
- {
- /* Receive always has a timeout applied. */
- if (s->timeout_x < 0)
- s->timeout_x = 7000;
- faxtester_set_timeout(s, s->timeout_x);
- if (parms.modem)
- {
- hdlc = (strcasecmp((const char *) parms.type, "PREAMBLE") == 0);
- short_train = (strcasecmp((const char *) parms.type, "TCF") != 0);
- faxtester_set_tx_type(s, T30_MODEM_NONE, 0, false, false);
- if (strcasecmp((const char *) parms.modem, "V.21") == 0)
- {
- faxtester_set_rx_type(s, T30_MODEM_V21, 300, false, true);
- }
- else if (strcasecmp((const char *) parms.modem, "V.17/14400") == 0)
- {
- faxtester_set_rx_type(s, T30_MODEM_V17, 14400, short_train, hdlc);
- }
- else if (strcasecmp((const char *) parms.modem, "V.17/12000") == 0)
- {
- faxtester_set_rx_type(s, T30_MODEM_V17, 12000, short_train, hdlc);
- }
- else if (strcasecmp((const char *) parms.modem, "V.17/9600") == 0)
- {
- faxtester_set_rx_type(s, T30_MODEM_V17, 9600, short_train, hdlc);
- }
- else if (strcasecmp((const char *) parms.modem, "V.17/7200") == 0)
- {
- faxtester_set_rx_type(s, T30_MODEM_V17, 7200, short_train, hdlc);
- }
- else if (strcasecmp((const char *) parms.modem, "V.29/9600") == 0)
- {
- faxtester_set_rx_type(s, T30_MODEM_V29, 9600, false, hdlc);
- }
- else if (strcasecmp((const char *) parms.modem, "V.29/7200") == 0)
- {
- faxtester_set_rx_type(s, T30_MODEM_V29, 7200, false, hdlc);
- }
- else if (strcasecmp((const char *) parms.modem, "V.27ter/4800") == 0)
- {
- faxtester_set_rx_type(s, T30_MODEM_V27TER, 4800, false, hdlc);
- }
- else if (strcasecmp((const char *) parms.modem, "V.27ter/2400") == 0)
- {
- faxtester_set_rx_type(s, T30_MODEM_V27TER, 2400, false, hdlc);
- }
- else
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "Unrecognised modem\n");
- }
- }
- if (strcasecmp((const char *) parms.type, "SET") == 0)
- {
- if (strcasecmp((const char *) parms.tag, "IDENT") == 0)
- strcpy(s->expected_rx_info.ident, (const char *) parms.value);
- else if (strcasecmp((const char *) parms.tag, "SUB") == 0)
- strcpy(s->expected_rx_info.sub_address, (const char *) parms.value);
- else if (strcasecmp((const char *) parms.tag, "SEP") == 0)
- strcpy(s->expected_rx_info.selective_polling_address, (const char *) parms.value);
- else if (strcasecmp((const char *) parms.tag, "PSA") == 0)
- strcpy(s->expected_rx_info.polled_sub_address, (const char *) parms.value);
- else if (strcasecmp((const char *) parms.tag, "SID") == 0)
- strcpy(s->expected_rx_info.sender_ident, (const char *) parms.value);
- else if (strcasecmp((const char *) parms.tag, "PWD") == 0)
- strcpy(s->expected_rx_info.password, (const char *) parms.value);
- free_node_parms(&parms);
- return 0;
- }
- else if (strcasecmp((const char *) parms.type, "CNG") == 0)
- {
- /* Look for CNG */
- faxtester_set_rx_type(s, T30_MODEM_CNG, 0, false, false);
- faxtester_set_tx_type(s, T30_MODEM_NONE, 0, false, false);
- }
- else if (strcasecmp((const char *) parms.type, "CED") == 0)
- {
- /* Look for CED */
- faxtester_set_rx_type(s, T30_MODEM_CED, 0, false, false);
- faxtester_set_tx_type(s, T30_MODEM_NONE, 0, false, false);
- }
- else if (strcasecmp((const char *) parms.type, "HDLC") == 0)
- {
- i = string_to_msg(buf, mask, (const char *) parms.value);
- bit_reverse(s->awaited, buf, abs(i));
- s->awaited_len = i;
- }
- else if (strcasecmp((const char *) parms.type, "TCF") == 0)
- {
- }
- else if (strcasecmp((const char *) parms.type, "MSG") == 0)
- {
- }
- else if (strcasecmp((const char *) parms.type, "PP") == 0)
- {
- }
- else if (strcasecmp((const char *) parms.type, "SILENCE") == 0)
- {
- faxtest_set_rx_silence(s);
- }
- else if (strcasecmp((const char *) parms.type, "CLEAR") == 0)
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "Far end should drop the call\n");
- faxtester_set_rx_type(s, T30_MODEM_NONE, 0, false, false);
- faxtester_set_tx_type(s, T30_MODEM_PAUSE, 0, s->timeout_x, false);
- s->test_for_call_clear = true;
- s->call_clear_timer = 0;
- }
- else
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "Unrecognised type '%s'\n", (const char *) parms.type);
- free_node_parms(&parms);
- return 0;
- }
- }
- else
- {
- faxtester_set_timeout(s, s->timeout_x);
- if (parms.modem)
- {
- hdlc = (strcasecmp((const char *) parms.type, "PREAMBLE") == 0);
- short_train = (strcasecmp((const char *) parms.type, "TCF") != 0);
- faxtester_set_rx_type(s, T30_MODEM_NONE, 0, false, false);
- if (strcasecmp((const char *) parms.modem, "V.21") == 0)
- {
- faxtester_set_tx_type(s, T30_MODEM_V21, 300, false, true);
- }
- else if (strcasecmp((const char *) parms.modem, "V.17/14400") == 0)
- {
- faxtester_set_tx_type(s, T30_MODEM_V17, 14400, short_train, hdlc);
- }
- else if (strcasecmp((const char *) parms.modem, "V.17/12000") == 0)
- {
- faxtester_set_tx_type(s, T30_MODEM_V17, 12000, short_train, hdlc);
- }
- else if (strcasecmp((const char *) parms.modem, "V.17/9600") == 0)
- {
- faxtester_set_tx_type(s, T30_MODEM_V17, 9600, short_train, hdlc);
- }
- else if (strcasecmp((const char *) parms.modem, "V.17/7200") == 0)
- {
- faxtester_set_tx_type(s, T30_MODEM_V17, 7200, short_train, hdlc);
- }
- else if (strcasecmp((const char *) parms.modem, "V.29/9600") == 0)
- {
- faxtester_set_tx_type(s, T30_MODEM_V29, 9600, false, hdlc);
- }
- else if (strcasecmp((const char *) parms.modem, "V.29/7200") == 0)
- {
- faxtester_set_tx_type(s, T30_MODEM_V29, 7200, false, hdlc);
- }
- else if (strcasecmp((const char *) parms.modem, "V.27ter/4800") == 0)
- {
- faxtester_set_tx_type(s, T30_MODEM_V27TER, 4800, false, hdlc);
- }
- else if (strcasecmp((const char *) parms.modem, "V.27ter/2400") == 0)
- {
- faxtester_set_tx_type(s, T30_MODEM_V27TER, 2400, false, hdlc);
- }
- else
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "Unrecognised modem\n");
- }
- }
- if (strcasecmp((const char *) parms.type, "SET") == 0)
- {
- if (strcasecmp((const char *) parms.tag, "IDENT") == 0)
- t30_set_tx_ident(s->far_t30, (const char *) parms.value);
- else if (strcasecmp((const char *) parms.tag, "SUB") == 0)
- t30_set_tx_sub_address(s->far_t30, (const char *) parms.value);
- else if (strcasecmp((const char *) parms.tag, "SEP") == 0)
- t30_set_tx_selective_polling_address(s->far_t30, (const char *) parms.value);
- else if (strcasecmp((const char *) parms.tag, "PSA") == 0)
- t30_set_tx_polled_sub_address(s->far_t30, (const char *) parms.value);
- else if (strcasecmp((const char *) parms.tag, "SID") == 0)
- t30_set_tx_sender_ident(s->far_t30, (const char *) parms.value);
- else if (strcasecmp((const char *) parms.tag, "PWD") == 0)
- t30_set_tx_password(s->far_t30, (const char *) parms.value);
- else if (strcasecmp((const char *) parms.tag, "RXFILE") == 0)
- {
- if (parms.value)
- t30_set_rx_file(s->far_t30, (const char *) parms.value, -1);
- else
- t30_set_rx_file(s->far_t30, output_tiff_file_name, -1);
- }
- else if (strcasecmp((const char *) parms.tag, "TXFILE") == 0)
- {
- sprintf(s->next_tx_file, "%s/%s", s->image_path, (const char *) parms.value);
- printf("Push '%s'\n", s->next_tx_file);
- }
- free_node_parms(&parms);
- return 0;
- }
- else if (strcasecmp((const char *) parms.type, "CALL") == 0)
- {
- if (s->far_fax)
- fax_restart(s->far_fax, false);
- else
- t38_terminal_restart(s->far_t38, false);
- fax_prepare(s);
- s->next_tx_file[0] = '\0';
- t30_set_rx_file(s->far_t30, output_tiff_file_name, -1);
- /* Avoid libtiff 3.8.2 and earlier bug on complex 2D lines. */
- t30_set_supported_output_compressions(s->far_t30, T4_COMPRESSION_T4_1D);
- if (parms.value)
- {
- sprintf(path, "%s/%s", s->image_path, (const char *) parms.value);
- t30_set_tx_file(s->far_t30, path, -1, -1);
- }
- free_node_parms(&parms);
- return 0;
- }
- else if (strcasecmp((const char *) parms.type, "ANSWER") == 0)
- {
- if (s->far_fax)
- fax_restart(s->far_fax, true);
- else
- t38_terminal_restart(s->far_t38, true);
- fax_prepare(s);
- s->next_tx_file[0] = '\0';
- /* Avoid libtiff 3.8.2 and earlier bug on complex 2D lines. */
- t30_set_supported_output_compressions(s->far_t30, T4_COMPRESSION_T4_1D);
- if (parms.value)
- {
- sprintf(path, "%s/%s", s->image_path, (const char *) parms.value);
- t30_set_tx_file(s->far_t30, path, -1, -1);
- }
- free_node_parms(&parms);
- return 0;
- }
- else if (strcasecmp((const char *) parms.type, "CNG") == 0)
- {
- faxtester_set_rx_type(s, T30_MODEM_NONE, 0, false, false);
- faxtester_set_tx_type(s, T30_MODEM_CNG, 0, false, false);
- }
- else if (strcasecmp((const char *) parms.type, "CED") == 0)
- {
- faxtester_set_rx_type(s, T30_MODEM_NONE, 0, false, false);
- faxtester_set_tx_type(s, T30_MODEM_CED, 0, false, false);
- }
- else if (strcasecmp((const char *) parms.type, "WAIT") == 0)
- {
- delay = (parms.value) ? atoi((const char *) parms.value) : 1;
- faxtester_set_rx_type(s, T30_MODEM_NONE, 0, false, false);
- faxtester_set_tx_type(s, T30_MODEM_PAUSE, 0, delay, false);
- }
- else if (strcasecmp((const char *) parms.type, "PREAMBLE") == 0)
- {
- flags = (parms.value) ? atoi((const char *) parms.value) : 37;
- faxtester_send_hdlc_flags(s, flags);
- }
- else if (strcasecmp((const char *) parms.type, "POSTAMBLE") == 0)
- {
- flags = (parms.value) ? atoi((const char *) parms.value) : 5;
- faxtester_send_hdlc_flags(s, flags);
- }
- else if (strcasecmp((const char *) parms.type, "HDLC") == 0)
- {
- i = string_to_msg(buf, mask, (const char *) parms.value);
- bit_reverse(buf, buf, abs(i));
- if (parms.crc_error && strcasecmp((const char *) parms.crc_error, "0") == 0)
- faxtester_send_hdlc_msg(s, buf, abs(i), false);
- else
- faxtester_send_hdlc_msg(s, buf, abs(i), true);
- }
- else if (strcasecmp((const char *) parms.type, "TCF") == 0)
- {
- i = (parms.value) ? atoi((const char *) parms.value) : 450;
- if (parms.pattern)
- {
- /* TODO: implement proper patterns */
- j = atoi((const char *) parms.pattern);
- memset(s->image, 0x55, j);
- if (i > j)
- memset(s->image + j, 0, i - j);
- }
- else
- {
- memset(s->image, 0, i);
- }
- s->image_ptr = 0;
- s->image_bit_ptr = 8;
- s->image_buffer = s->image;
- s->image_len = i;
- }
- else if (strcasecmp((const char *) parms.type, "MSG") == 0)
- {
- /* A non-ECM page */
- min_row_bits = (parms.min_bits) ? atoi((const char *) parms.min_bits) : 0;
- sprintf(path, "%s/%s", s->image_path, (const char *) parms.value);
- if (t4_tx_init(&t4_tx_state, path, -1, -1) == NULL)
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "Failed to init T.4 send\n");
- printf("Test failed\n");
- exit(2);
- }
- t4_tx_set_header_info(&t4_tx_state, NULL);
- compression_type = T4_COMPRESSION_T4_1D;
- if (parms.compression)
- {
- if (strcasecmp((const char *) parms.compression, "T.4 1D") == 0)
- compression_type = T4_COMPRESSION_T4_1D;
- else if (strcasecmp((const char *) parms.compression, "T.4 2D") == 0)
- compression_type = T4_COMPRESSION_T4_2D;
- else if (strcasecmp((const char *) parms.compression, "T.6") == 0)
- compression_type = T4_COMPRESSION_T6;
- else if (strcasecmp((const char *) parms.compression, "T.85") == 0)
- compression_type = T4_COMPRESSION_T85;
- }
- if (t4_tx_set_tx_image_format(&t4_tx_state,
- compression_type,
- T4_SUPPORT_WIDTH_215MM
- | T4_SUPPORT_LENGTH_US_LETTER
- | T4_SUPPORT_LENGTH_US_LEGAL
- | T4_SUPPORT_LENGTH_UNLIMITED,
- T4_RESOLUTION_R8_STANDARD
- | T4_RESOLUTION_R8_FINE
- | T4_RESOLUTION_R8_SUPERFINE
- | T4_RESOLUTION_R16_SUPERFINE
- | T4_RESOLUTION_200_100
- | T4_RESOLUTION_200_200
- | T4_RESOLUTION_200_400
- | T4_RESOLUTION_300_300
- | T4_RESOLUTION_300_600
- | T4_RESOLUTION_400_400
- | T4_RESOLUTION_400_800
- | T4_RESOLUTION_600_600
- | T4_RESOLUTION_600_1200
- | T4_RESOLUTION_1200_1200,
- T4_RESOLUTION_100_100
- | T4_RESOLUTION_200_200
- | T4_RESOLUTION_300_300
- | T4_RESOLUTION_400_400
- | T4_RESOLUTION_600_600
- | T4_RESOLUTION_1200_1200) < 0)
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "Failed to set T.4 compression\n");
- printf("Test failed\n");
- exit(2);
- }
- t4_tx_set_min_bits_per_row(&t4_tx_state, min_row_bits);
- if (t4_tx_start_page(&t4_tx_state))
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "Failed to start T.4 send\n");
- printf("Test failed\n");
- exit(2);
- }
- s->image_len = t4_tx_get(&t4_tx_state, s->image, sizeof(s->image));
- if (parms.bad_rows)
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "We need to corrupt the image\n");
- corrupt_image(s, (const char *) parms.bad_rows);
- }
- t4_tx_release(&t4_tx_state);
- span_log(&s->logging, SPAN_LOG_FLOW, "Non-ECM image is %d bytes (min row bits %d)\n", s->image_len, min_row_bits);
- s->image_ptr = 0;
- s->image_bit_ptr = 8;
- s->image_buffer = s->image;
- }
- else if (strcasecmp((const char *) parms.type, "PP") == 0)
- {
- min_row_bits = (parms.min_bits) ? atoi((const char *) parms.min_bits) : 0;
- ecm_block = (parms.block) ? atoi((const char *) parms.block) : 0;
- ecm_frame_size = (parms.frame_size) ? atoi((const char *) parms.frame_size) : 64;
- i = (parms.crc_error) ? atoi((const char *) parms.crc_error) : -1;
- sprintf(path, "%s/%s", s->image_path, (const char *) parms.value);
- if (t4_tx_init(&t4_tx_state, path, -1, -1) == NULL)
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "Failed to init T.4 send\n");
- printf("Test failed\n");
- exit(2);
- }
- t4_tx_set_header_info(&t4_tx_state, NULL);
- compression_type = T4_COMPRESSION_T4_1D;
- if (parms.compression)
- {
- if (strcasecmp((const char *) parms.compression, "T.4 1D") == 0)
- compression_type = T4_COMPRESSION_T4_1D;
- else if (strcasecmp((const char *) parms.compression, "T.4 2D") == 0)
- compression_type = T4_COMPRESSION_T4_2D;
- else if (strcasecmp((const char *) parms.compression, "T.6") == 0)
- compression_type = T4_COMPRESSION_T6;
- else if (strcasecmp((const char *) parms.compression, "T.85") == 0)
- compression_type = T4_COMPRESSION_T85;
- }
- if (t4_tx_set_tx_image_format(&t4_tx_state,
- compression_type,
- T4_SUPPORT_WIDTH_215MM
- | T4_SUPPORT_LENGTH_US_LETTER
- | T4_SUPPORT_LENGTH_US_LEGAL
- | T4_SUPPORT_LENGTH_UNLIMITED,
- T4_RESOLUTION_R8_STANDARD
- | T4_RESOLUTION_R8_FINE
- | T4_RESOLUTION_R8_SUPERFINE
- | T4_RESOLUTION_R16_SUPERFINE
- | T4_RESOLUTION_200_100
- | T4_RESOLUTION_200_200
- | T4_RESOLUTION_200_400
- | T4_RESOLUTION_300_300
- | T4_RESOLUTION_300_600
- | T4_RESOLUTION_400_400
- | T4_RESOLUTION_400_800
- | T4_RESOLUTION_600_600
- | T4_RESOLUTION_600_1200
- | T4_RESOLUTION_1200_1200,
- T4_RESOLUTION_100_100
- | T4_RESOLUTION_200_200
- | T4_RESOLUTION_300_300
- | T4_RESOLUTION_400_400
- | T4_RESOLUTION_600_600
- | T4_RESOLUTION_1200_1200) < 0)
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "Failed to set T.4 compression\n");
- printf("Test failed\n");
- exit(2);
- }
- t4_tx_set_min_bits_per_row(&t4_tx_state, min_row_bits);
- if (t4_tx_start_page(&t4_tx_state))
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "Failed to start T.4 send\n");
- printf("Test failed\n");
- exit(2);
- }
- /*endif*/
- s->image_len = t4_tx_get(&t4_tx_state, s->image, sizeof(s->image));
- if (parms.bad_rows)
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "We need to corrupt the image\n");
- corrupt_image(s, (const char *) parms.bad_rows);
- }
- /*endif*/
- t4_tx_release(&t4_tx_state);
- span_log(&s->logging, SPAN_LOG_FLOW, "ECM image is %d bytes (min row bits %d)\n", s->image_len, min_row_bits);
- faxtester_set_ecm_image_buffer(s, ecm_block, ecm_frame_size, i);
- }
- else if (strcasecmp((const char *) parms.type, "CLEAR") == 0)
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "Time to drop the call\n");
- faxtester_set_rx_type(s, T30_MODEM_NONE, 0, false, false);
- faxtester_set_tx_type(s, T30_MODEM_PAUSE, 0, s->timeout_x, false);
- t30_terminate(s->far_t30);
- free_node_parms(&parms);
- return 0;
- }
- else if (strcasecmp((const char *) parms.type, "STATUS") == 0)
- {
- if (parms.value)
- {
- for (i = 0; t30_status[i].code >= 0; i++)
- {
- if (strcmp(t30_status[i].tag, (const char *) parms.value) == 0)
- break;
- }
- if (t30_status[i].code >= 0)
- delay = t30_status[i].code;
- else
- delay = atoi((const char *) parms.value);
- t30_get_transfer_statistics(s->far_t30, &t30_stats);
- if (delay == t30_stats.current_status)
- span_log(&s->logging, SPAN_LOG_FLOW, "Expected status (%s) found\n", t30_status[i].tag);
- else
- span_log(&s->logging, SPAN_LOG_FLOW, "Expected status %s, but found %s (%d)\n", t30_status[i].tag, t30_status[t30_stats.current_status].tag, t30_stats.current_status);
- if (delay != t30_stats.current_status)
- {
- printf("Test failed\n");
- exit(2);
- }
- }
- free_node_parms(&parms);
- return 0;
- }
- else
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "Unrecognised type '%s'\n", (const char *) parms.type);
- free_node_parms(&parms);
- return 0;
- }
- /*endif*/
- }
- /*endif*/
- free_node_parms(&parms);
- return 1;
- }
- /*- End of function --------------------------------------------------------*/
- static int parse_config(faxtester_state_t *s, xmlNodePtr cur)
- {
- xmlChar *x;
- xmlChar *y;
- while (cur)
- {
- if (xmlStrcmp(cur->name, (const xmlChar *) "path") == 0)
- {
- x = NULL;
- y = NULL;
- if ((x = xmlGetProp(cur, (const xmlChar *) "type"))
- &&
- (y = xmlGetProp(cur, (const xmlChar *) "value")))
- {
- if (strcasecmp((const char *) x, "IMAGE") == 0)
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "Found '%s' '%s'\n", (char *) x, (char *) y);
- strcpy(s->image_path, (const char *) y);
- }
- /*endif*/
- }
- /*endif*/
- if (x)
- xmlFree(x);
- /*endif*/
- if (y)
- xmlFree(y);
- /*endif*/
- }
- /*endif*/
- cur = cur->next;
- }
- /*endwhile*/
- return -1;
- }
- /*- End of function --------------------------------------------------------*/
- static int parse_test_group(faxtester_state_t *s, xmlNodePtr cur, const char *test)
- {
- xmlChar *x;
- while (cur)
- {
- if (xmlStrcmp(cur->name, (const xmlChar *) "test") == 0)
- {
- if ((x = xmlGetProp(cur, (const xmlChar *) "name")))
- {
- if (xmlStrcmp(x, (const xmlChar *) test) == 0)
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "Found '%s'\n", (char *) x);
- s->cur = cur->xmlChildrenNode;
- xmlFree(x);
- return 0;
- }
- /*endif*/
- xmlFree(x);
- }
- /*endif*/
- }
- /*endif*/
- cur = cur->next;
- }
- /*endwhile*/
- return -1;
- }
- /*- End of function --------------------------------------------------------*/
- static int get_test_set(faxtester_state_t *s, const char *test_file, const char *test)
- {
- xmlParserCtxtPtr ctxt;
- xmlNodePtr cur;
- if ((ctxt = xmlNewParserCtxt()) == NULL)
- {
- fprintf(stderr, "Failed to allocate XML parser context\n");
- return -1;
- }
- /* parse the file, activating the DTD validation option */
- if ((s->doc = xmlCtxtReadFile(ctxt, test_file, NULL, XML_PARSE_XINCLUDE | XML_PARSE_DTDVALID)) == NULL)
- {
- fprintf(stderr, "Failed to read the XML document\n");
- return -1;
- }
- if (ctxt->valid == 0)
- {
- fprintf(stderr, "Failed to validate the XML document\n");
- xmlFreeDoc(s->doc);
- s->doc = NULL;
- xmlFreeParserCtxt(ctxt);
- return -1;
- }
- xmlFreeParserCtxt(ctxt);
- /* Check the document is of the right kind */
- if ((cur = xmlDocGetRootElement(s->doc)) == NULL)
- {
- xmlFreeDoc(s->doc);
- s->doc = NULL;
- fprintf(stderr, "Empty document\n");
- return -1;
- }
- /*endif*/
- if (xmlStrcmp(cur->name, (const xmlChar *) "fax-tests"))
- {
- xmlFreeDoc(s->doc);
- s->doc = NULL;
- fprintf(stderr, "Document of the wrong type, root node != fax-tests\n");
- return -1;
- }
- /*endif*/
- cur = cur->xmlChildrenNode;
- while (cur && xmlIsBlankNode(cur))
- cur = cur->next;
- /*endwhile*/
- if (cur == NULL)
- {
- fprintf(stderr, "XML test not found\n");
- return -1;
- }
- /*endif*/
- xmlCleanupParser();
- while (cur)
- {
- if (xmlStrcmp(cur->name, (const xmlChar *) "config") == 0)
- parse_config(s, cur->xmlChildrenNode);
- /*endif*/
- if (xmlStrcmp(cur->name, (const xmlChar *) "test-group") == 0)
- {
- if (parse_test_group(s, cur->xmlChildrenNode, test) == 0)
- return 0;
- /*endif*/
- }
- /*endif*/
- cur = cur->next;
- }
- /*endwhile*/
- fprintf(stderr, "XML test not found\n");
- return -1;
- }
- /*- End of function --------------------------------------------------------*/
- SPAN_DECLARE(logging_state_t *) faxtester_get_logging_state(faxtester_state_t *s)
- {
- return &s->logging;
- }
- /*- End of function --------------------------------------------------------*/
- faxtester_state_t *faxtester_init(faxtester_state_t *s, const char *test_file, const char *test)
- {
- if (s == NULL)
- {
- if ((s = (faxtester_state_t *) malloc(sizeof(*s))) == NULL)
- return NULL;
- }
- /*endif*/
- memset(s, 0, sizeof(*s));
- span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
- span_log_set_protocol(&s->logging, "TST");
- fax_modems_init(&s->modems,
- false,
- hdlc_accept,
- hdlc_underflow_handler,
- non_ecm_put_bit,
- t38_non_ecm_buffer_get_bit,
- tone_detected,
- s);
- fax_modems_set_tep_mode(&s->modems, false);
- fax_modems_set_rx_active(&s->modems, true);
- faxtester_set_timeout(s, -1);
- s->timein_x = -1;
- s->timeout_x = -1;
- faxtester_set_tx_type(s, T30_MODEM_NONE, 0, false, false);
- strcpy(s->image_path, ".");
- s->next_tx_file[0] = '\0';
- if (get_test_set(s, test_file, test) < 0)
- {
- /* TODO: free the state, if it was allocated. */
- return NULL;
- }
- /*endif*/
- memset(&s->expected_rx_info, 0, sizeof(s->expected_rx_info));
- return s;
- }
- /*- End of function --------------------------------------------------------*/
- int faxtester_release(faxtester_state_t *s)
- {
- if (s->doc)
- {
- xmlFreeDoc(s->doc);
- s->doc = NULL;
- }
- return 0;
- }
- /*- End of function --------------------------------------------------------*/
- int faxtester_free(faxtester_state_t *s)
- {
- faxtester_release(s);
- free(s);
- return 0;
- }
- /*- End of function --------------------------------------------------------*/
- /*- End of file ------------------------------------------------------------*/
|