├── .cvsignore ├── opal ├── .cvsignore ├── t38modem_2005.sln ├── t38modem_2010.sln ├── opalutils.h ├── opalutils.cxx ├── modemstrm.h ├── h323ep.h ├── sipep.h ├── modemep.h ├── manager.h ├── modemstrm.cxx └── t38modem_2005.vcproj ├── version.h ├── precompile.cxx ├── HylaFAX └── config.ttyx ├── fcs.h ├── tone_gen.h ├── drivers.h ├── fcs.cxx ├── t30.h ├── t30tone.h ├── dle.h ├── hdlc.h ├── Updates.txt ├── t30.cxx ├── pmodeme.h ├── drv_c0c.h ├── drv_pty.h ├── pmodemi.h ├── pmodem.h ├── dle.cxx ├── drivers.cxx ├── tone_gen.cxx ├── Makefile ├── pmodem.cxx ├── Changes.txt ├── pmutils.cxx ├── pmodemi.cxx ├── enginebase.h ├── t30tone.cxx ├── pmutils.h ├── t38engine.h ├── hdlc.cxx ├── ReadMe.txt └── enginebase.cxx /.cvsignore: -------------------------------------------------------------------------------- 1 | obj_* 2 | Debug 3 | Release 4 | NoTrace 5 | *.ncb 6 | *.vcproj.*.user 7 | *.suo 8 | -------------------------------------------------------------------------------- /opal/.cvsignore: -------------------------------------------------------------------------------- 1 | obj_* 2 | Debug 3 | Release 4 | NoTrace 5 | *.ncb 6 | *.vcproj.*.user 7 | *.suo 8 | -------------------------------------------------------------------------------- /version.h: -------------------------------------------------------------------------------- 1 | /* 2 | * version.h 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Open H323 Project 7 | * 8 | * The contents of this file are subject to the Mozilla Public License 9 | * Version 1.0 (the "License"); you may not use this file except in 10 | * compliance with the License. You may obtain a copy of the License at 11 | * http://www.mozilla.org/MPL/ 12 | * 13 | * Software distributed under the License is distributed on an "AS IS" 14 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 15 | * the License for the specific language governing rights and limitations 16 | * under the License. 17 | * 18 | * The Original Code is Open H323 Library. 19 | * 20 | * The Initial Developer of the Original Code is Vyacheslav Frolov 21 | * 22 | * Contributor(s): Equivalence Pty ltd 23 | * 24 | */ 25 | 26 | #ifndef _T38M_VERSION_H 27 | #define _T38M_VERSION_H 28 | 29 | #define MAJOR_VERSION 4 30 | #define MINOR_VERSION 6 31 | #define BUILD_TYPE PProcess::ReleaseCode 32 | #define BUILD_NUMBER 2 33 | 34 | #endif // _T38M_VERSION_H 35 | 36 | -------------------------------------------------------------------------------- /opal/t38modem_2005.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 9.00 2 | # Visual C++ Express 2005 3 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "t38modem", "t38modem_2005.vcproj", "{5684EA1E-9DEC-4701-A81E-FBF8133A77B5}" 4 | EndProject 5 | Global 6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 7 | Debug|Win32 = Debug|Win32 8 | No Trace|Win32 = No Trace|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {5684EA1E-9DEC-4701-A81E-FBF8133A77B5}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {5684EA1E-9DEC-4701-A81E-FBF8133A77B5}.Debug|Win32.Build.0 = Debug|Win32 14 | {5684EA1E-9DEC-4701-A81E-FBF8133A77B5}.No Trace|Win32.ActiveCfg = No Trace|Win32 15 | {5684EA1E-9DEC-4701-A81E-FBF8133A77B5}.No Trace|Win32.Build.0 = No Trace|Win32 16 | {5684EA1E-9DEC-4701-A81E-FBF8133A77B5}.Release|Win32.ActiveCfg = Release|Win32 17 | {5684EA1E-9DEC-4701-A81E-FBF8133A77B5}.Release|Win32.Build.0 = Release|Win32 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /opal/t38modem_2010.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 11.00 2 | # Visual Studio 2010 3 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "t38modem", "t38modem_2010.vcxproj", "{5684EA1E-9DEC-4701-A81E-FBF8133A77B5}" 4 | EndProject 5 | Global 6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 7 | Debug|Win32 = Debug|Win32 8 | No Trace|Win32 = No Trace|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {5684EA1E-9DEC-4701-A81E-FBF8133A77B5}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {5684EA1E-9DEC-4701-A81E-FBF8133A77B5}.Debug|Win32.Build.0 = Debug|Win32 14 | {5684EA1E-9DEC-4701-A81E-FBF8133A77B5}.No Trace|Win32.ActiveCfg = No Trace|Win32 15 | {5684EA1E-9DEC-4701-A81E-FBF8133A77B5}.No Trace|Win32.Build.0 = No Trace|Win32 16 | {5684EA1E-9DEC-4701-A81E-FBF8133A77B5}.Release|Win32.ActiveCfg = Release|Win32 17 | {5684EA1E-9DEC-4701-A81E-FBF8133A77B5}.Release|Win32.Build.0 = Release|Win32 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /precompile.cxx: -------------------------------------------------------------------------------- 1 | /* 2 | * precompile.cxx 3 | * 4 | * PWLib application source file for t38modem 5 | * 6 | * Precompiled header generation file. 7 | * 8 | * Copyright (c) 1993-1998 Equivalence Pty. Ltd. 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Portable Windows Library. 21 | * 22 | * The Initial Developer of the Original Code is Equivalence Pty. Ltd. 23 | * 24 | * Portions are Copyright (C) 1993 Free Software Foundation, Inc. 25 | * All Rights Reserved. 26 | * 27 | * Contributor(s): ______________________________________. 28 | */ 29 | 30 | #include 31 | 32 | 33 | // End of File /////////////////////////////////////////////////////////////// 34 | -------------------------------------------------------------------------------- /opal/opalutils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * opalutils.h 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2007 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): 25 | * 26 | * $Log: opalutils.h,v $ 27 | * Revision 1.1 2007-07-20 14:26:40 vfrolov 28 | * Initial revision 29 | * 30 | * Revision 1.1 2007/07/20 14:26:40 vfrolov 31 | * Initial revision 32 | * 33 | * 34 | */ 35 | 36 | #ifndef _OPALUTILS_H 37 | #define _OPALUTILS_H 38 | 39 | extern PString GetPartyName(const PString & party); 40 | 41 | #endif // _OPALUTILS_H 42 | 43 | -------------------------------------------------------------------------------- /HylaFAX/config.ttyx: -------------------------------------------------------------------------------- 1 | # 2 | # HylaFAX configuration for a T38FAX Pseudo Modem 3 | # 4 | 5 | SessionTracing: 0x2FFF 6 | RingsBeforeAnswer: 1 7 | 8 | ModemType: Class1 # use class 1 interface 9 | ModemFlowControl: rtscts # default 10 | 11 | ModemRevQueryCmd: AT+FREV? 12 | 13 | # 14 | # AT#CID=10 enables ANI/DNIS reporting between the 15 | # first and second RINGs in the form: 16 | # 17 | # RING 18 | # NMBR = 19 | # NDID = 20 | # RING 21 | # 22 | #ModemResetCmds: "AT#CID=10" # enable ANI/DNIS reporting 23 | #RingsBeforeAnswer: 2 # collect info between two RINGs 24 | #QualifyCID: etc/cid # CID access control list file 25 | #CIDNumber: "NMBR = " # pattern string for calling number 26 | #CIDName: "NDID = " # pattern string for called number 27 | 28 | 29 | # 30 | # T.38 dial modifiers 31 | # 32 | # F - enable T.38 mode request after dialing 33 | # V - disable T.38 mode request after dialing (remote host should do it) 34 | # 35 | # calling/called number dial modifiers 36 | # 37 | # L - reset and begin of calling number 38 | # D - continue of called number 39 | # 40 | #ModemDialCmd: ATDF%s # user can override F by dial V 41 | #ModemDialCmd: ATDV%s # user can override V by dial F 42 | #ModemDialCmd: ATD%sF # user can't override F 43 | #ModemDialCmd: ATD%sV # user can't override V 44 | #ModemDialCmd: ATD%sVL # user can't override V or calling number 45 | 46 | -------------------------------------------------------------------------------- /fcs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * fcs.h 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2003 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): Equivalence Pty ltd 25 | * 26 | * $Log: fcs.h,v $ 27 | * Revision 1.2 2004-02-17 13:22:58 vfrolov 28 | * Fixed MSVC compile errors 29 | * 30 | * Revision 1.2 2004/02/17 13:22:58 vfrolov 31 | * Fixed MSVC compile errors 32 | * 33 | * Revision 1.1 2003/12/04 13:38:26 vfrolov 34 | * Initial revision 35 | * 36 | * 37 | */ 38 | 39 | #ifndef _FCS_H 40 | #define _FCS_H 41 | 42 | #include "pmutils.h" 43 | 44 | /////////////////////////////////////////////////////////////// 45 | class FCS 46 | { 47 | public: 48 | FCS() : fcs(0xFFFF) {} 49 | 50 | void build(const void *pBuf, PINDEX count); 51 | operator WORD() const { return WORD(~fcs); } 52 | 53 | protected: 54 | 55 | DWORD fcs; 56 | }; 57 | /////////////////////////////////////////////////////////////// 58 | 59 | #endif // _FCS_H 60 | 61 | -------------------------------------------------------------------------------- /opal/opalutils.cxx: -------------------------------------------------------------------------------- 1 | /* 2 | * opalutils.cxx 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2007-2008 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): 25 | * 26 | * $Log: opalutils.cxx,v $ 27 | * Revision 1.2 2008-09-10 11:15:00 frolov 28 | * Ported to OPAL SVN trunk 29 | * 30 | * Revision 1.2 2008/09/10 11:15:00 frolov 31 | * Ported to OPAL SVN trunk 32 | * 33 | * Revision 1.1 2007/07/20 14:26:40 vfrolov 34 | * Initial revision 35 | * 36 | */ 37 | 38 | #include 39 | 40 | #include 41 | 42 | #include "opalutils.h" 43 | 44 | #define new PNEW 45 | 46 | ///////////////////////////////////////////////////////////////////////////// 47 | PString GetPartyName(const PString & party) 48 | { 49 | PINDEX beg = party.Find(':'); 50 | 51 | if (beg != P_MAX_INDEX) 52 | beg++; 53 | 54 | PINDEX end = party.Find('@'); 55 | 56 | if (end != P_MAX_INDEX) 57 | end--; 58 | 59 | return party(beg, end); 60 | } 61 | ///////////////////////////////////////////////////////////////////////////// 62 | 63 | -------------------------------------------------------------------------------- /tone_gen.h: -------------------------------------------------------------------------------- 1 | /* 2 | * tone_gen.h 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2010 Vyacheslav Frolov 7 | * 8 | * t38modem Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is t38modem. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): 25 | * 26 | * $Log: tone_gen.h,v $ 27 | * Revision 1.1 2010-10-12 16:43:00 vfrolov 28 | * Initial revision 29 | * 30 | * Revision 1.1 2010/10/12 16:43:00 vfrolov 31 | * Initial revision 32 | * 33 | */ 34 | 35 | #ifndef _TONE_GEN_H 36 | #define _TONE_GEN_H 37 | 38 | /////////////////////////////////////////////////////////////// 39 | class ToneGenerator : public PObject 40 | { 41 | PCLASSINFO(ToneGenerator, PObject); 42 | 43 | public: 44 | 45 | enum ToneType { 46 | ttSilence, 47 | ttCng, 48 | ttCed, 49 | ttRing, 50 | ttBusy, 51 | }; 52 | 53 | ToneGenerator(ToneType tt = ttSilence); 54 | void Read(void * buffer, PINDEX amount); 55 | ToneType Type() const { return type; } 56 | 57 | protected: 58 | ToneType type; 59 | PINDEX bytesOn; 60 | PINDEX bytesOff; 61 | const BYTE *pToneOn; 62 | PINDEX bytesToneOn; 63 | PINDEX index; 64 | }; 65 | /////////////////////////////////////////////////////////////// 66 | 67 | #endif // _TONE_GEN_H 68 | 69 | -------------------------------------------------------------------------------- /drivers.h: -------------------------------------------------------------------------------- 1 | /* 2 | * drivers.h 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2004-2007 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): 25 | * 26 | * $Log: drivers.h,v $ 27 | * Revision 1.2 2007-01-29 12:44:41 vfrolov 28 | * Added ability to put args to drivers 29 | * 30 | * Revision 1.2 2007/01/29 12:44:41 vfrolov 31 | * Added ability to put args to drivers 32 | * 33 | * Revision 1.1 2004/07/07 12:38:32 vfrolov 34 | * The code for pseudo-tty (pty) devices that communicates with fax application formed to PTY driver. 35 | * 36 | * 37 | */ 38 | 39 | #ifndef _DRIVERS_H 40 | #define _DRIVERS_H 41 | 42 | /////////////////////////////////////////////////////////////// 43 | class PseudoModem; 44 | 45 | class PseudoModemDrivers : protected PObject 46 | { 47 | PCLASSINFO(PseudoModemDrivers, PObject); 48 | public: 49 | static PseudoModem *CreateModem( 50 | const PString &tty, 51 | const PString &route, 52 | const PConfigArgs &args, 53 | const PNotifier &callbackEndPoint 54 | ); 55 | 56 | static PString ArgSpec(); 57 | static PStringArray Descriptions(); 58 | }; 59 | /////////////////////////////////////////////////////////////// 60 | 61 | #endif // _DRIVERS_H 62 | 63 | -------------------------------------------------------------------------------- /fcs.cxx: -------------------------------------------------------------------------------- 1 | /* 2 | * fcs.cxx 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2003-2004 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): Equivalence Pty ltd 25 | * 26 | * $Log: fcs.cxx,v $ 27 | * Revision 1.3 2004-07-06 16:07:24 vfrolov 28 | * Included ptlib.h for precompiling 29 | * 30 | * Revision 1.3 2004/07/06 16:07:24 vfrolov 31 | * Included ptlib.h for precompiling 32 | * 33 | * Revision 1.2 2004/02/17 13:22:50 vfrolov 34 | * Fixed MSVC compile errors 35 | * 36 | * Revision 1.1 2003/12/04 13:29:00 vfrolov 37 | * Initial revision 38 | * 39 | * 40 | */ 41 | 42 | #include 43 | #include "fcs.h" 44 | 45 | /////////////////////////////////////////////////////////////// 46 | 47 | #define new PNEW 48 | 49 | /////////////////////////////////////////////////////////////// 50 | void FCS::build(const void *_pBuf, PINDEX count) 51 | { 52 | const BYTE *pBuf = (const BYTE *)_pBuf; 53 | 54 | for (PINDEX i = 0 ; i < count ; i++) { 55 | BYTE c = *(pBuf++); 56 | for (BYTE m = 0x80 ; m ; m >>= 1) { 57 | fcs <<= 1; 58 | if (c & m) 59 | fcs ^= 0x10000; 60 | if (fcs & 0x10000) 61 | fcs ^= 0x11021; 62 | } 63 | } 64 | } 65 | /////////////////////////////////////////////////////////////// 66 | 67 | -------------------------------------------------------------------------------- /t30.h: -------------------------------------------------------------------------------- 1 | /* 2 | * t30.h 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2003-2009 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): Equivalence Pty ltd 25 | * 26 | * $Log: t30.h,v $ 27 | * Revision 1.4 2009-07-02 11:39:05 vfrolov 28 | * Added T30() constructor 29 | * 30 | * Revision 1.4 2009/07/02 11:39:05 vfrolov 31 | * Added T30() constructor 32 | * 33 | * Revision 1.3 2008/09/10 11:15:00 frolov 34 | * Ported to OPAL SVN trunk 35 | * 36 | * Revision 1.2 2003/12/04 15:51:54 vfrolov 37 | * Removed unused DIS member 38 | * 39 | * Revision 1.1 2003/12/04 13:38:52 vfrolov 40 | * Initial revision 41 | * 42 | */ 43 | 44 | #ifndef _T30_H 45 | #define _T30_H 46 | 47 | #include "pmutils.h" 48 | 49 | /////////////////////////////////////////////////////////////// 50 | class T30 51 | { 52 | public: 53 | T30() : cfr(FALSE), ecm(FALSE) {} 54 | void v21Begin() { v21frame = PBYTEArray(); } 55 | void v21Data(void *pBuf, PINDEX len) { v21frame.Concatenate(PBYTEArray((BYTE *)pBuf, len)); } 56 | void v21End(PBoolean sent); 57 | PBoolean hdlcOnly() const { return cfr && ecm; } 58 | 59 | private: 60 | PBYTEArray v21frame; 61 | PBoolean cfr; 62 | PBoolean ecm; 63 | }; 64 | /////////////////////////////////////////////////////////////// 65 | 66 | #endif // _T30_H 67 | 68 | -------------------------------------------------------------------------------- /t30tone.h: -------------------------------------------------------------------------------- 1 | /* 2 | * t30tone.h 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2002-2010 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): Equivalence Pty ltd 25 | * 26 | * $Log: t30tone.h,v $ 27 | * Revision 1.6 2010-10-12 16:46:25 vfrolov 28 | * Implemented fake streams 29 | * 30 | * Revision 1.6 2010/10/12 16:46:25 vfrolov 31 | * Implemented fake streams 32 | * 33 | * Revision 1.5 2010/09/10 18:00:44 vfrolov 34 | * Cleaned up code 35 | * 36 | * Revision 1.4 2008/09/10 11:15:00 frolov 37 | * Ported to OPAL SVN trunk 38 | * 39 | * Revision 1.3 2007/03/23 10:14:36 vfrolov 40 | * Implemented voice mode functionality 41 | * 42 | * Revision 1.2 2004/07/07 07:52:07 vfrolov 43 | * Moved ptlib.h including to *.cxx for precompiling 44 | * 45 | * Revision 1.1 2002/04/30 10:59:10 vfrolov 46 | * Initial revision 47 | * 48 | */ 49 | 50 | #ifndef _T30TONE_H 51 | #define _T30TONE_H 52 | 53 | /////////////////////////////////////////////////////////////// 54 | class T30ToneDetect : public PObject 55 | { 56 | PCLASSINFO(T30ToneDetect, PObject); 57 | 58 | public: 59 | 60 | T30ToneDetect(); 61 | ~T30ToneDetect(); 62 | 63 | PBoolean Write(const void * buffer, PINDEX len); 64 | 65 | protected: 66 | 67 | long *cng_filter_buf; 68 | PINDEX index; 69 | long power; 70 | int cng_on_count; 71 | int cng_off_count; 72 | int cng_phase; 73 | }; 74 | /////////////////////////////////////////////////////////////// 75 | 76 | #endif // _T30TONE_H 77 | 78 | -------------------------------------------------------------------------------- /dle.h: -------------------------------------------------------------------------------- 1 | /* 2 | * dle.h 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2001-2009 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): Equivalence Pty ltd 25 | * 26 | * $Log: dle.h,v $ 27 | * Revision 1.5 2009-06-29 13:18:23 vfrolov 28 | * Disabled changing bitRev in Clean() 29 | * 30 | * Revision 1.5 2009/06/29 13:18:23 vfrolov 31 | * Disabled changing bitRev in Clean() 32 | * 33 | * Revision 1.4 2008/09/10 11:15:00 frolov 34 | * Ported to OPAL SVN trunk 35 | * 36 | * Revision 1.3 2002/04/19 14:29:30 vfrolov 37 | * Added Copyright header 38 | * 39 | * Revision 1.2 2002/01/10 06:10:02 craigs 40 | * Added MPL header 41 | * 42 | * Revision 1.1 2002/01/01 23:06:54 craigs 43 | * Initial version 44 | * 45 | */ 46 | 47 | #ifndef _DLE_H 48 | #define _DLE_H 49 | 50 | #include "pmutils.h" 51 | 52 | /////////////////////////////////////////////////////////////// 53 | class DLEData : public DataStream 54 | { 55 | PCLASSINFO(DLEData, DataStream); 56 | public: 57 | DLEData() : dle(FALSE), recvEtx(FALSE), bitRev(FALSE) { } 58 | 59 | int PutDleData(const void *pBuf, PINDEX count); 60 | int GetDleData(void *pBuf, PINDEX count); 61 | 62 | void BitRev(PBoolean _bitRev) { bitRev = _bitRev; } 63 | 64 | virtual void Clean() { 65 | DataStream::Clean(); 66 | dle = recvEtx = FALSE; 67 | } 68 | protected: 69 | 70 | PBoolean dle; 71 | PBoolean recvEtx; 72 | PBoolean bitRev; 73 | }; 74 | /////////////////////////////////////////////////////////////// 75 | 76 | #endif // _DLE_H 77 | 78 | -------------------------------------------------------------------------------- /hdlc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * hdlc.h 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2003-2008 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): Equivalence Pty ltd 25 | * 26 | * $Log: hdlc.h,v $ 27 | * Revision 1.2 2008-09-10 11:15:00 frolov 28 | * Ported to OPAL SVN trunk 29 | * 30 | * Revision 1.2 2008/09/10 11:15:00 frolov 31 | * Ported to OPAL SVN trunk 32 | * 33 | * Revision 1.1 2003/12/04 13:38:39 vfrolov 34 | * Initial revision 35 | * 36 | */ 37 | 38 | #ifndef _HDLC_H 39 | #define _HDLC_H 40 | 41 | #include "fcs.h" 42 | 43 | /////////////////////////////////////////////////////////////// 44 | class HDLC 45 | { 46 | public: 47 | HDLC(); 48 | void PutRawData(DataStream *_inData); 49 | void PutHdlcData(DataStream *_inData); 50 | void GetRawStart(PINDEX flags = 0); 51 | void GetHdlcStart(PBoolean sync); 52 | int GetData(void *pBuf, PINDEX count); 53 | PBoolean isFcsOK(); 54 | int getLastChar() { return lastChar; } 55 | PINDEX getRawCount() { return rawCount; } 56 | void resetRawCount() { rawCount = 0; } 57 | 58 | private: 59 | void pack(const void *pBuf, PINDEX count, PBoolean flag = FALSE); 60 | PBoolean sync(BYTE b); 61 | PBoolean skipFlag(BYTE b); 62 | PBoolean unpack(BYTE b); 63 | int GetInData(void *pBuf, PINDEX count); 64 | int GetRawData(void *pBuf, PINDEX count); 65 | int GetHdlcData(void *pBuf, PINDEX count); 66 | 67 | int inDataType; 68 | int outDataType; 69 | DataStream *inData; 70 | DataStream outData; 71 | FCS fcs; 72 | int lastChar; 73 | PINDEX rawCount; 74 | 75 | BYTE rawByte; 76 | int rawByteLen; 77 | int rawOnes; 78 | DWORD hdlcChunk; 79 | int hdlcChunkLen; 80 | 81 | enum { 82 | stEof, 83 | stSync, 84 | stSkipFlags, 85 | stData, 86 | } hdlcState; 87 | }; 88 | /////////////////////////////////////////////////////////////// 89 | 90 | #endif // _HDLC_H 91 | 92 | -------------------------------------------------------------------------------- /Updates.txt: -------------------------------------------------------------------------------- 1 | Updates.txt 2 | - updates to t38modem to work with ptlib-2.16.2 and opal-3.16.2 3 | 4 | pmutils.cxx: commented out the do-while loop enclosing line 107 5 | drivers.cxx: commented out the myPTRACE calls in lines 143, 151, 156 6 | t38engine.cxx: changed the include for opal/buildopts.h to opal_config.h in line 270 7 | t38engine.cxx: added parentheses around the && portions of the if statement in lines 1645-1648 8 | main_process.cxx: changed the include for opal/buildopts.h to opal_config.h in line 64 9 | opal/opalutils.cxx: changed the include for opal/buildopts.h to opal_config.h in line 40 10 | opal/modemep.cxx: changed the include for opal/buildopts.h to opal_config.h in line 135 11 | opal/modemep.cxx: added media type as third argument in line 997 12 | opal/modemep.cxx: changed attribute type as third argument in line 252 13 | opal/modemep.cxx: added PMutex type specifier to the argument in line 512 14 | opal/modemep.cxx: declared variable as PString in line 576 15 | opal/modemstrm.cxx: changed the include for opal/buildopts.h to opal_config.h in line 71 16 | opal/modemstrm.cxx: updated variable name for "isOpen" in lines 103, 122, 138, 150, 182, 206, 265, 317 17 | opal/modemstrm.cxx: updated variable name for "isSource" in line 230 18 | opal/h323ep.cxx: changed the include for opal/buildopts.h to opal_config.h in line 119 19 | opal/h323ep.cxx: changed the RTP Session type in lines 614, 617 20 | opal/h323ep.cxx: commented out RTP Session calls in lines 614, 616, 617 21 | opal/sipep.cxx: changed the include for opal/buildopts.h to opal_config.h in line 129 22 | opal/sipep.h: changed the parameters for CreateConnection in line 79 23 | opal/sipep.cxx: changed the parameters in MySIPConnection in line 158 24 | opal/sipep.cxx: changed the parameters in SIPConnection in line 160 25 | opal/sipep.cxx: changed the parameters for CreateConnection in line 488 26 | opal/sipep.cxx: modified the name of the variable "call" in line 490 27 | opal/sipep.cxx: changed the argument names in MySIPConnection in line 492 28 | opal/sipep.cxx: changed the RTP Session type in lines 626, 629 29 | opal/sipep.cxx: commented out RTP Session calls in lines 626, 628, 629 30 | opal/sipep.cxx: commented out m_retry403 parameter in line 421 31 | opal/sipep.cxx: commented out retry403 variable in line 339 32 | opal/sipep.cxx: commented out if-else statement in lines 402-405 33 | opal/manager.cxx: changed the include for opal/buildopts.h to opal_config.h in line 85 34 | opal/manager.cxx: commented out the unused STUN server in lines 253-265 35 | opal/manager.cxx: modified the cout message in line 296 36 | opal/fake_codecs.cxx: changed the include for opal/buildopts.h to opal_config.h in line 43 37 | -------------------------------------------------------------------------------- /t30.cxx: -------------------------------------------------------------------------------- 1 | /* 2 | * t30.cxx 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2003-2008 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): Equivalence Pty ltd 25 | * 26 | * $Log: t30.cxx,v $ 27 | * Revision 1.5 2008-09-10 11:15:00 frolov 28 | * Ported to OPAL SVN trunk 29 | * 30 | * Revision 1.5 2008/09/10 11:15:00 frolov 31 | * Ported to OPAL SVN trunk 32 | * 33 | * Revision 1.4 2005/02/04 10:18:49 vfrolov 34 | * Fixed warnings for No Trace build 35 | * 36 | * Revision 1.3 2004/07/06 16:07:24 vfrolov 37 | * Included ptlib.h for precompiling 38 | * 39 | * Revision 1.2 2003/12/04 15:50:27 vfrolov 40 | * Fixed extracting ECM flag 41 | * 42 | * Revision 1.1 2003/12/04 13:38:46 vfrolov 43 | * Initial revision 44 | * 45 | */ 46 | 47 | #include 48 | #include "t30.h" 49 | 50 | /////////////////////////////////////////////////////////////// 51 | 52 | #define new PNEW 53 | 54 | /////////////////////////////////////////////////////////////// 55 | void T30::v21End(PBoolean myPTRACE_PARAM(sent)) 56 | { 57 | int size = v21frame.GetSize(); 58 | PString msg; 59 | 60 | if (size < 3) 61 | msg = "too short"; 62 | else 63 | if (v21frame[0] != 0xFF) 64 | msg = "w/o address field"; 65 | else 66 | if ((v21frame[1] & 0xF7) != 0xC0) 67 | msg = "w/o control field"; 68 | else { 69 | switch (v21frame[2]) { 70 | case 0x41: 71 | case 0x41 | 0x80: 72 | msg = "DCS"; 73 | if (v21frame.GetSize() > 3+3 && (v21frame[3+2] & 1) && (v21frame[3+3] & 0x20)) { 74 | ecm = TRUE; 75 | msg += " with ECM"; 76 | } else { 77 | ecm = FALSE; 78 | } 79 | 80 | cfr = FALSE; 81 | break; 82 | case 0x21: 83 | case 0x21 | 0x80: 84 | msg = "CFR"; 85 | cfr = TRUE; 86 | break; 87 | } 88 | } 89 | myPTRACE(2, "T38Modem\t" << PString(sent ? "-->" : "<--") << " v21frame " << msg << PRTHEX(v21frame)); 90 | } 91 | /////////////////////////////////////////////////////////////// 92 | 93 | -------------------------------------------------------------------------------- /pmodeme.h: -------------------------------------------------------------------------------- 1 | /* 2 | * pmodeme.cxx 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2001-2010 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): Equivalence Pty ltd 25 | * 26 | * $Log: pmodeme.h,v $ 27 | * Revision 1.8 2010-10-06 16:54:19 vfrolov 28 | * Redesigned engine opening/closing 29 | * 30 | * Revision 1.8 2010/10/06 16:54:19 vfrolov 31 | * Redesigned engine opening/closing 32 | * 33 | * Revision 1.7 2010/09/29 11:52:59 vfrolov 34 | * Redesigned engine attaching/detaching 35 | * 36 | * Revision 1.6 2008/09/10 11:15:00 frolov 37 | * Ported to OPAL SVN trunk 38 | * 39 | * Revision 1.5 2007/03/23 10:14:35 vfrolov 40 | * Implemented voice mode functionality 41 | * 42 | * Revision 1.4 2004/07/07 12:38:32 vfrolov 43 | * The code for pseudo-tty (pty) devices that communicates with fax application formed to PTY driver. 44 | * 45 | * Revision 1.3 2002/04/19 14:29:33 vfrolov 46 | * Added Copyright header 47 | * 48 | * Revision 1.2 2002/01/10 06:10:02 craigs 49 | * Added MPL header 50 | * 51 | * Revision 1.1 2002/01/01 23:06:54 craigs 52 | * Initial version 53 | * 54 | */ 55 | 56 | #ifndef _PMODEME_H 57 | #define _PMODEME_H 58 | 59 | #include "pmodemi.h" 60 | 61 | /////////////////////////////////////////////////////////////// 62 | class ModemEngineBody; 63 | class PseudoModemBody; 64 | 65 | class ModemEngine : public ModemThreadChild 66 | { 67 | PCLASSINFO(ModemEngine, ModemThreadChild); 68 | public: 69 | 70 | /**@name Construction */ 71 | //@{ 72 | ModemEngine(PseudoModemBody &_parent); 73 | ~ModemEngine(); 74 | //@} 75 | 76 | /**@name Operations */ 77 | //@{ 78 | PBoolean IsReady() const; 79 | PBoolean Request(PStringToString &request) const; 80 | virtual T38Engine *NewPtrT38Engine() const; 81 | virtual EngineBase *NewPtrUserInputEngine() const; 82 | const PString &ptyName() const { return Parent().ptyName(); } 83 | const PString &modemToken() const { return Parent().modemToken(); } 84 | //@} 85 | 86 | protected: 87 | PseudoModemBody &Parent() const { return (PseudoModemBody &)parent; } 88 | virtual void Main(); 89 | void ToPtyQ(const void *buf, PINDEX count) const { Parent().ToOutPtyQ(buf, count); } 90 | 91 | ModemEngineBody *body; 92 | }; 93 | /////////////////////////////////////////////////////////////// 94 | 95 | #endif // _PMODEME_H 96 | 97 | -------------------------------------------------------------------------------- /opal/modemstrm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * modemstrm.h 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2007-2010 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): 25 | * 26 | * $Log: modemstrm.h,v $ 27 | * Revision 1.6 2010-10-06 16:54:19 vfrolov 28 | * Redesigned engine opening/closing 29 | * 30 | * Revision 1.6 2010/10/06 16:54:19 vfrolov 31 | * Redesigned engine opening/closing 32 | * 33 | * Revision 1.5 2009/12/08 15:06:22 vfrolov 34 | * Fixed incompatibility with OPAL trunk 35 | * 36 | * Revision 1.4 2009/11/20 16:37:27 vfrolov 37 | * Fixed audio class application blocking by forced T.38 mode 38 | * 39 | * Revision 1.3 2009/10/27 19:03:50 vfrolov 40 | * Added ability to re-open T38Engine 41 | * Added ability to prepare IFP packets with adaptive delay/period 42 | * 43 | * Revision 1.2 2008/09/10 11:15:00 frolov 44 | * Ported to OPAL SVN trunk 45 | * 46 | * Revision 1.1 2007/05/28 12:47:52 vfrolov 47 | * Initial revision 48 | * 49 | */ 50 | 51 | #ifndef _MY_MODEM_MEDIA_STREAM_H 52 | #define _MY_MODEM_MEDIA_STREAM_H 53 | 54 | #include 55 | 56 | ///////////////////////////////////////////////////////////////////////////// 57 | class T38Engine; 58 | 59 | class T38ModemMediaStream : public OpalMediaStream 60 | { 61 | PCLASSINFO(T38ModemMediaStream, OpalMediaStream); 62 | public: 63 | /**@name Construction */ 64 | //@{ 65 | /**Construct a new media stream. 66 | */ 67 | T38ModemMediaStream( 68 | OpalConnection & conn, 69 | unsigned sessionID, ///< Session number for stream 70 | PBoolean isSource, ///< Is a source stream 71 | T38Engine *engine 72 | ); 73 | 74 | ~T38ModemMediaStream(); 75 | //@} 76 | 77 | /**@name Overrides of OpalMediaStream class */ 78 | //@{ 79 | virtual PBoolean Open(); 80 | virtual void InternalClose(); 81 | virtual void OnStartMediaPatch(); 82 | 83 | virtual PBoolean ReadPacket( 84 | RTP_DataFrame & packet 85 | ); 86 | 87 | virtual PBoolean WritePacket( 88 | RTP_DataFrame & packet 89 | ); 90 | 91 | virtual PBoolean IsSynchronous() const { return FALSE; } 92 | //@} 93 | 94 | protected: 95 | long currentSequenceNumber; 96 | #if PTRACING 97 | int totallost; 98 | #endif 99 | T38Engine * t38engine; 100 | }; 101 | ///////////////////////////////////////////////////////////////////////////// 102 | 103 | #endif // _MY_MODEM_MEDIA_STREAM_H 104 | 105 | -------------------------------------------------------------------------------- /drv_c0c.h: -------------------------------------------------------------------------------- 1 | /* 2 | * drv_c0c.h 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2004-2008 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): 25 | * 26 | * $Log: drv_c0c.h,v $ 27 | * Revision 1.5 2008-09-11 07:41:48 frolov 28 | * Ported to OPAL SVN trunk 29 | * 30 | * Revision 1.5 2008/09/11 07:41:48 frolov 31 | * Ported to OPAL SVN trunk 32 | * 33 | * Revision 1.4 2007/01/29 12:44:41 vfrolov 34 | * Added ability to put args to drivers 35 | * 36 | * Revision 1.3 2005/02/10 15:04:58 vfrolov 37 | * Disabled I/C calls for closed ports 38 | * 39 | * Revision 1.2 2004/07/19 08:31:06 vfrolov 40 | * Fixed "friend declaration requires class-key" 41 | * 42 | * Revision 1.1 2004/07/07 13:36:46 vfrolov 43 | * Initial revision 44 | * 45 | */ 46 | 47 | #ifndef _DRV_C0C_H 48 | #define _DRV_C0C_H 49 | 50 | #ifdef _WIN32 51 | #define MODEM_DRIVER_C0C 52 | #endif 53 | 54 | #ifdef MODEM_DRIVER_C0C 55 | 56 | #include "pmodemi.h" 57 | 58 | /////////////////////////////////////////////////////////////// 59 | class InC0C; 60 | class OutC0C; 61 | 62 | class PseudoModemC0C : public PseudoModemBody 63 | { 64 | PCLASSINFO(PseudoModemC0C, PseudoModemBody); 65 | 66 | public: 67 | /**@name Construction */ 68 | //@{ 69 | PseudoModemC0C( 70 | const PString &_tty, 71 | const PString &_route, 72 | const PConfigArgs &args, 73 | const PNotifier &_callbackEndPoint 74 | ); 75 | ~PseudoModemC0C(); 76 | //@} 77 | 78 | /**@name static functions */ 79 | //@{ 80 | static PBoolean CheckTty(const PString &_tty); 81 | static PString ArgSpec(); 82 | static PStringArray Description(); 83 | //@} 84 | 85 | virtual PBoolean IsReady() const; 86 | 87 | protected: 88 | /**@name Overrides from class PseudoModemBody */ 89 | //@{ 90 | const PString &ttyPath() const; 91 | ModemThreadChild *GetPtyNotifier(); 92 | PBoolean StartAll(); 93 | void StopAll(); 94 | void MainLoop(); 95 | //@} 96 | 97 | private: 98 | BOOL OpenC0C(); 99 | void CloseC0C(); 100 | BOOL OutPnpId(); 101 | BOOL WaitReady(); 102 | BOOL IsOpenC0C() const { return hC0C != INVALID_HANDLE_VALUE; } 103 | 104 | HANDLE hC0C; 105 | InC0C *inC0C; 106 | OutC0C *outC0C; 107 | BOOL reset; 108 | BOOL ready; 109 | 110 | PString ptypath; 111 | 112 | friend class InC0C; 113 | friend class OutC0C; 114 | }; 115 | /////////////////////////////////////////////////////////////// 116 | 117 | #endif // MODEM_DRIVER_C0C 118 | 119 | #endif // _DRV_C0C_H 120 | 121 | -------------------------------------------------------------------------------- /drv_pty.h: -------------------------------------------------------------------------------- 1 | /* 2 | * drv_pty.h 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2001-2008 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): Equivalence Pty ltd 25 | * 26 | * $Log: drv_pty.h,v $ 27 | * Revision 1.4 2008-09-10 11:15:00 frolov 28 | * Ported to OPAL SVN trunk 29 | * 30 | * Revision 1.4 2008/09/10 11:15:00 frolov 31 | * Ported to OPAL SVN trunk 32 | * 33 | * Revision 1.3 2007/01/29 12:44:41 vfrolov 34 | * Added ability to put args to drivers 35 | * 36 | * Revision 1.2 2004/07/19 08:31:06 vfrolov 37 | * Fixed "friend declaration requires class-key" 38 | * 39 | * Revision 1.1 2004/07/07 12:38:32 vfrolov 40 | * The code for pseudo-tty (pty) devices that communicates with fax application formed to PTY driver. 41 | * 42 | * 43 | * Log: pty.h,v 44 | * 45 | * Revision 1.3 2002/04/19 14:29:37 vfrolov 46 | * Added Copyright header 47 | * 48 | * Revision 1.2 2002/01/10 06:10:03 craigs 49 | * Added MPL header 50 | * 51 | * Revision 1.1 2002/01/01 23:06:54 craigs 52 | * Initial version 53 | * 54 | */ 55 | 56 | #ifndef _DRV_PTY_H 57 | #define _DRV_PTY_H 58 | 59 | #ifndef _WIN32 60 | #define MODEM_DRIVER_Pty 61 | #endif 62 | 63 | #ifdef MODEM_DRIVER_Pty 64 | 65 | #include "pmodemi.h" 66 | 67 | /////////////////////////////////////////////////////////////// 68 | class InPty; 69 | class OutPty; 70 | 71 | class PseudoModemPty : public PseudoModemBody 72 | { 73 | PCLASSINFO(PseudoModemPty, PseudoModemBody); 74 | 75 | public: 76 | /**@name Construction */ 77 | //@{ 78 | PseudoModemPty( 79 | const PString &_tty, 80 | const PString &_route, 81 | const PConfigArgs &args, 82 | const PNotifier &_callbackEndPoint 83 | ); 84 | ~PseudoModemPty(); 85 | //@} 86 | 87 | /**@name static functions */ 88 | //@{ 89 | static PBoolean CheckTty(const PString &_tty); 90 | static PString ArgSpec(); 91 | static PStringArray Description(); 92 | //@} 93 | 94 | protected: 95 | /**@name Overrides from class PseudoModemBody */ 96 | //@{ 97 | const PString &ttyPath() const; 98 | ModemThreadChild *GetPtyNotifier(); 99 | PBoolean StartAll(); 100 | void StopAll(); 101 | void MainLoop(); 102 | //@} 103 | 104 | private: 105 | PBoolean OpenPty(); 106 | void ClosePty(); 107 | PBoolean IsOpenPty() const { return hPty >= 0; } 108 | 109 | int hPty; 110 | InPty *inPty; 111 | OutPty *outPty; 112 | 113 | PString ptypath; 114 | PString ttypath; 115 | 116 | friend class InPty; 117 | friend class OutPty; 118 | }; 119 | /////////////////////////////////////////////////////////////// 120 | 121 | #endif // MODEM_DRIVER_Pty 122 | 123 | #endif // _DRV_PTY_H 124 | 125 | -------------------------------------------------------------------------------- /opal/h323ep.h: -------------------------------------------------------------------------------- 1 | /* 2 | * h323ep.h 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2007-2010 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): 25 | * 26 | * $Log: h323ep.h,v $ 27 | * Revision 1.7 2010-03-15 13:40:27 vfrolov 28 | * Removed unused code 29 | * 30 | * Revision 1.7 2010/03/15 13:40:27 vfrolov 31 | * Removed unused code 32 | * 33 | * Revision 1.6 2010/01/21 16:05:33 vfrolov 34 | * Changed --h323-audio to accept multiple wildcards 35 | * Implemented OPAL-Enable-Audio route option 36 | * Renamed route option OPAL-H323-Bearer-Capability to OPAL-Bearer-Capability 37 | * 38 | * Revision 1.5 2009/12/23 17:54:24 vfrolov 39 | * Implemented --h323-bearer-capability option 40 | * 41 | * Revision 1.4 2009/11/10 11:30:57 vfrolov 42 | * Implemented G.711 fallback to fax pass-through mode 43 | * 44 | * Revision 1.3 2009/07/22 14:42:49 vfrolov 45 | * Added Descriptions(args) to endpoints 46 | * 47 | * Revision 1.2 2008/09/10 11:15:00 frolov 48 | * Ported to OPAL SVN trunk 49 | * 50 | * Revision 1.1 2007/05/28 12:47:52 vfrolov 51 | * Initial revision 52 | * 53 | */ 54 | 55 | #ifndef _MY_H323EP_H 56 | #define _MY_H323EP_H 57 | 58 | #include 59 | #include "../pmutils.h" 60 | 61 | ///////////////////////////////////////////////////////////////////////////// 62 | // 63 | // myH323EndPoint 64 | // creates MyH323Connection 65 | // 66 | class OpalMediaFormat; 67 | 68 | class MyH323EndPoint : public H323EndPoint 69 | { 70 | PCLASSINFO(MyH323EndPoint, H323EndPoint); 71 | 72 | public: 73 | /**@name Construction */ 74 | //@{ 75 | /**Create a new endpoint. 76 | */ 77 | MyH323EndPoint( 78 | OpalManager & manager) 79 | : H323EndPoint(manager) 80 | {} 81 | //@} 82 | 83 | static PString ArgSpec(); 84 | static PStringArray Descriptions(); 85 | static PStringArray Descriptions(const PConfigArgs & args); 86 | static PBoolean Create(OpalManager & mgr, const PConfigArgs & args); 87 | PBoolean Initialise(const PConfigArgs & args); 88 | 89 | virtual H323Connection * CreateConnection( 90 | OpalCall & call, ///< Call object to attach the connection to 91 | const PString & token, ///< Call token for new connection 92 | void * userData, ///< Arbitrary user data from MakeConnection 93 | OpalTransport & transport, ///< Transport for connection 94 | const PString & alias, ///< Alias for outgoing call 95 | const H323TransportAddress & address, ///< Address for outgoing call 96 | H323SignalPDU * setupPDU, ///< Setup PDU for incoming call 97 | unsigned options = 0, 98 | OpalConnection::StringOptions * stringOptions = NULL ///< complex string options 99 | ); 100 | 101 | static PStringToString defaultStringOptions; 102 | }; 103 | ///////////////////////////////////////////////////////////////////////////// 104 | 105 | #endif // _MY_H323EP_H 106 | 107 | -------------------------------------------------------------------------------- /opal/sipep.h: -------------------------------------------------------------------------------- 1 | /* 2 | * sipep.h 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2007-2010 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): 25 | * 26 | * $Log: sipep.h,v $ 27 | * Revision 1.6 2010-03-15 13:40:28 vfrolov 28 | * Removed unused code 29 | * 30 | * Revision 1.6 2010/03/15 13:40:28 vfrolov 31 | * Removed unused code 32 | * 33 | * Revision 1.5 2010/01/21 16:00:55 vfrolov 34 | * Changed --sip-audio to accept multiple wildcards 35 | * Implemented OPAL-Enable-Audio route option 36 | * 37 | * Revision 1.4 2009/11/10 11:30:57 vfrolov 38 | * Implemented G.711 fallback to fax pass-through mode 39 | * 40 | * Revision 1.3 2009/07/22 14:42:49 vfrolov 41 | * Added Descriptions(args) to endpoints 42 | * 43 | * Revision 1.2 2008/09/10 11:15:00 frolov 44 | * Ported to OPAL SVN trunk 45 | * 46 | * Revision 1.1 2007/05/28 12:47:52 vfrolov 47 | * Initial revision 48 | * 49 | */ 50 | 51 | #ifndef _MY_SIPEP_H 52 | #define _MY_SIPEP_H 53 | 54 | #include 55 | #include "manager.h" 56 | #include "../pmutils.h" 57 | 58 | ///////////////////////////////////////////////////////////////////////////// 59 | 60 | class OpalRTPEndPoint; 61 | 62 | class MyRTPEndPoint : public MyManagerEndPoint 63 | { 64 | protected: 65 | MyRTPEndPoint(MyManager & manager, OpalRTPEndPoint * endpoint); 66 | 67 | static PString GetArgumentSpec(); 68 | bool Initialise(PArgList & args, ostream & output, bool verbose); 69 | 70 | bool SetUIMode(const PCaselessString & str); 71 | 72 | protected: 73 | OpalRTPEndPoint & m_endpoint; 74 | }; 75 | 76 | ///////////////////////////////////////////////////////////////////////////// 77 | 78 | class MySIPRegisterHandler : public SIPRegisterHandler 79 | { 80 | PCLASSINFO(MySIPRegisterHandler, SIPRegisterHandler); 81 | 82 | public: 83 | MySIPRegisterHandler( 84 | SIPEndPoint & ep, 85 | const SIPRegister::Params & params 86 | ) 87 | : SIPRegisterHandler(ep, params) 88 | {} 89 | 90 | virtual void OnReceivedIntervalTooBrief(SIPTransaction & transaction, SIP_PDU & response); 91 | }; 92 | 93 | ///////////////////////////////////////////////////////////////////////////// 94 | 95 | class MySIPEndPoint : public SIPEndPoint, public MyRTPEndPoint 96 | { 97 | PCLASSINFO(MySIPEndPoint, SIPEndPoint) 98 | public: 99 | MySIPEndPoint(MyManager & manager); 100 | 101 | ~MySIPEndPoint() 102 | { 103 | cout << "Deleting SIPEndPoint..." << endl; 104 | } 105 | 106 | static PString GetArgumentSpec(); 107 | virtual bool Initialise(PArgList & args, bool verbose, const PString & defaultRoute); 108 | 109 | virtual void OnRegistrationStatus(const RegistrationStatus & status); 110 | bool DoRegistration(ostream & output, 111 | bool verbose, 112 | const PString & aor, 113 | const PString & pwd, 114 | const PArgList & args, 115 | const char * authId, 116 | const char * realm, 117 | const char * proxy, 118 | const char * mode, 119 | const char * ttl, 120 | const char * resultFile); 121 | SIPRegisterHandler * CreateRegisterHandler(const SIPRegister::Params & params); 122 | }; 123 | 124 | ///////////////////////////////////////////////////////////////////////////// 125 | 126 | #endif // _MY_SIPEP_H 127 | 128 | -------------------------------------------------------------------------------- /opal/modemep.h: -------------------------------------------------------------------------------- 1 | /* 2 | * modemep.h 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2007-2010 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): 25 | * 26 | * $Log: modemep.h,v $ 27 | * Revision 1.8 2010-03-15 13:40:28 vfrolov 28 | * Removed unused code 29 | * 30 | * Revision 1.8 2010/03/15 13:40:28 vfrolov 31 | * Removed unused code 32 | * 33 | * Revision 1.7 2010/02/16 16:21:25 vfrolov 34 | * Added --force-fax-mode and --no-force-t38-mode options 35 | * 36 | * Revision 1.6 2010/02/08 17:30:31 vfrolov 37 | * Disabled OPAL version < 3.8.0 38 | * 39 | * Revision 1.5 2009/11/02 18:02:19 vfrolov 40 | * Removed pre v3.7 compatibility code 41 | * 42 | * Revision 1.4 2009/07/22 14:42:49 vfrolov 43 | * Added Descriptions(args) to endpoints 44 | * 45 | * Revision 1.3 2009/07/13 15:08:17 vfrolov 46 | * Ported to OPAL SVN trunk 47 | * 48 | * Revision 1.2 2008/09/10 11:15:00 frolov 49 | * Ported to OPAL SVN trunk 50 | * 51 | * Revision 1.1 2007/05/28 12:47:52 vfrolov 52 | * Initial revision 53 | * 54 | */ 55 | 56 | #ifndef _MODEM_EP_H 57 | #define _MODEM_EP_H 58 | 59 | ///////////////////////////////////////////////////////////////////////////// 60 | #define PACK_VERSION(major, minor, build) (((((major) << 8) + (minor)) << 8) + (build)) 61 | 62 | #if !(PACK_VERSION(OPAL_MAJOR, OPAL_MINOR, OPAL_BUILD) >= PACK_VERSION(3, 16, 1)) 63 | #error *** Incompatible OPAL version (required >= 3.16.1) *** 64 | #endif 65 | 66 | #undef PACK_VERSION 67 | ///////////////////////////////////////////////////////////////////////////// 68 | #include 69 | #include "manager.h" 70 | ///////////////////////////////////////////////////////////////////////////// 71 | class PseudoModem; 72 | class PseudoModemQ; 73 | 74 | class ModemEndPoint : public OpalFaxEndPoint, public MyManagerEndPoint 75 | { 76 | PCLASSINFO(ModemEndPoint, OpalFaxEndPoint); 77 | public: 78 | /**@name Construction */ 79 | //@{ 80 | /**Create a new endpoint. 81 | */ 82 | ModemEndPoint( 83 | MyManager & manager, ///< Manager of all endpoints. 84 | const char * g711Prefix = "fax", ///< Prefix for URL style address strings 85 | const char * t38Prefix = "t38" ///< Prefix for URL style address strings 86 | ); 87 | ~ModemEndPoint(); 88 | //@} 89 | static PString GetArgumentSpec(); 90 | virtual bool Initialise(PArgList & args, bool verbose, const PString & defaultRoute); 91 | 92 | PseudoModem * PMAlloc(const PString &number) const; 93 | void PMFree(PseudoModem *pmodem) const; 94 | 95 | /**@name Overrides from OpalEndPoint */ 96 | //@{ 97 | virtual PSafePtr MakeConnection( 98 | OpalCall & call, ///< Owner of connection 99 | const PString & party, ///< Remote party to call 100 | void * userData = NULL, ///< Arbitrary data to pass to connection 101 | unsigned int options = 0, ///< Options to pass to conneciton 102 | OpalConnection::StringOptions * stringOptions = NULL 103 | ); 104 | 105 | virtual OpalMediaFormatList GetMediaFormats() const; 106 | //@} 107 | 108 | static PStringToString defaultStringOptions; 109 | 110 | protected: 111 | PseudoModemQ *pmodem_pool; 112 | PString m_prefix; 113 | 114 | PDECLARE_NOTIFIER(PObject, ModemEndPoint, OnMyCallback); 115 | }; 116 | ///////////////////////////////////////////////////////////////////////////// 117 | 118 | #endif // _MODEM_EP_H 119 | 120 | -------------------------------------------------------------------------------- /pmodemi.h: -------------------------------------------------------------------------------- 1 | /* 2 | * pmodemi.h 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2001-2010 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): Equivalence Pty ltd 25 | * 26 | * $Log: pmodemi.h,v $ 27 | * Revision 1.10 2010-10-06 16:54:19 vfrolov 28 | * Redesigned engine opening/closing 29 | * 30 | * Revision 1.10 2010/10/06 16:54:19 vfrolov 31 | * Redesigned engine opening/closing 32 | * 33 | * Revision 1.9 2010/09/29 11:52:59 vfrolov 34 | * Redesigned engine attaching/detaching 35 | * 36 | * Revision 1.8 2009/07/08 18:43:44 vfrolov 37 | * Added PseudoModem::ttyName() 38 | * 39 | * Revision 1.7 2008/09/10 11:15:00 frolov 40 | * Ported to OPAL SVN trunk 41 | * 42 | * Revision 1.6 2007/03/23 10:14:36 vfrolov 43 | * Implemented voice mode functionality 44 | * 45 | * Revision 1.5 2004/07/07 12:38:32 vfrolov 46 | * The code for pseudo-tty (pty) devices that communicates with fax application formed to PTY driver. 47 | * 48 | * Revision 1.4 2002/05/15 16:18:00 vfrolov 49 | * Implemented per modem routing for I/C calls 50 | * 51 | * Revision 1.3 2002/03/05 12:32:02 vfrolov 52 | * Added Copyright header 53 | * Changed class hierarchy 54 | * PseudoModem is abstract 55 | * PseudoModemBody is child of PseudoModem 56 | * Added PseudoModemQ::CreateModem() to create instances 57 | * 58 | * Revision 1.2 2002/01/10 06:10:03 craigs 59 | * Added MPL header 60 | * 61 | * Revision 1.1 2002/01/01 23:06:54 craigs 62 | * Initial version 63 | * 64 | */ 65 | 66 | #ifndef _PMODEMI_H 67 | #define _PMODEMI_H 68 | 69 | #include "pmodem.h" 70 | 71 | /////////////////////////////////////////////////////////////// 72 | class ModemEngine; 73 | 74 | class PseudoModemBody : public PseudoModem 75 | { 76 | PCLASSINFO(PseudoModemBody, PseudoModem); 77 | public: 78 | 79 | /**@name Construction */ 80 | //@{ 81 | PseudoModemBody(const PString &_tty, const PString &_route, const PNotifier &_callbackEndPoint); 82 | ~PseudoModemBody(); 83 | //@} 84 | 85 | /**@name Operations */ 86 | //@{ 87 | PBYTEArray *FromInPtyQ() { return inPtyQ.Dequeue(); } 88 | void ToOutPtyQ(const void *buf, PINDEX count) { ToPtyQ(buf, count, TRUE); }; 89 | //@} 90 | 91 | virtual PBoolean IsReady() const; 92 | PBoolean CheckRoute(const PString &number) const; 93 | PBoolean Request(PStringToString &request) const; 94 | virtual T38Engine *NewPtrT38Engine() const; 95 | virtual EngineBase *NewPtrUserInputEngine() const; 96 | 97 | const PNotifier &GetCallbackEndPoint() const { return callbackEndPoint; } 98 | 99 | protected: 100 | virtual const PString &ttyPath() const = 0; 101 | virtual ModemThreadChild *GetPtyNotifier() = 0; 102 | virtual PBoolean StartAll(); 103 | virtual void StopAll(); 104 | virtual void MainLoop() = 0; 105 | 106 | PBoolean AddModem() const; 107 | PBYTEArray *FromOutPtyQ() { return outPtyQ.Dequeue(); } 108 | void ToInPtyQ(PBYTEArray *buf) { inPtyQ.Enqueue(buf); } 109 | void ToInPtyQ(const void *buf, PINDEX count) { ToPtyQ(buf, count, FALSE); }; 110 | 111 | PMutex Mutex; 112 | 113 | private: 114 | void Main(); 115 | void ToPtyQ(const void *buf, PINDEX count, PBoolean OutQ); 116 | 117 | PString route; 118 | const PNotifier callbackEndPoint; 119 | ModemEngine *engine; 120 | 121 | PBYTEArrayQ outPtyQ; 122 | PBYTEArrayQ inPtyQ; 123 | }; 124 | /////////////////////////////////////////////////////////////// 125 | 126 | #endif // _PMODEMI_H 127 | 128 | -------------------------------------------------------------------------------- /pmodem.h: -------------------------------------------------------------------------------- 1 | /* 2 | * pmodem.h 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2001-2010 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): Equivalence Pty ltd 25 | * 26 | * $Log: pmodem.h,v $ 27 | * Revision 1.11 2010-10-06 16:54:19 vfrolov 28 | * Redesigned engine opening/closing 29 | * 30 | * Revision 1.11 2010/10/06 16:54:19 vfrolov 31 | * Redesigned engine opening/closing 32 | * 33 | * Revision 1.10 2010/09/29 11:52:59 vfrolov 34 | * Redesigned engine attaching/detaching 35 | * 36 | * Revision 1.9 2009/07/08 18:43:44 vfrolov 37 | * Added PseudoModem::ttyName() 38 | * 39 | * Revision 1.8 2008/09/10 11:15:00 frolov 40 | * Ported to OPAL SVN trunk 41 | * 42 | * Revision 1.7 2007/03/23 10:14:35 vfrolov 43 | * Implemented voice mode functionality 44 | * 45 | * Revision 1.6 2007/01/29 12:44:41 vfrolov 46 | * Added ability to put args to drivers 47 | * 48 | * Revision 1.5 2004/07/07 12:38:32 vfrolov 49 | * The code for pseudo-tty (pty) devices that communicates with fax application formed to PTY driver. 50 | * 51 | * Revision 1.4 2002/05/15 16:17:49 vfrolov 52 | * Implemented per modem routing for I/C calls 53 | * 54 | * Revision 1.3 2002/03/05 12:31:58 vfrolov 55 | * Added Copyright header 56 | * Changed class hierarchy 57 | * PseudoModem is abstract 58 | * PseudoModemBody is child of PseudoModem 59 | * Added PseudoModemQ::CreateModem() to create instances 60 | * 61 | * Revision 1.2 2002/01/10 06:10:02 craigs 62 | * Added MPL header 63 | * 64 | * Revision 1.1 2002/01/01 23:06:54 craigs 65 | * Initial version 66 | * 67 | */ 68 | 69 | #ifndef _PMODEM_H 70 | #define _PMODEM_H 71 | 72 | #include "pmutils.h" 73 | 74 | /////////////////////////////////////////////////////////////// 75 | class T38Engine; 76 | class EngineBase; 77 | 78 | class PseudoModem : public ModemThread 79 | { 80 | PCLASSINFO(PseudoModem, ModemThread); 81 | public: 82 | 83 | /**@name Construction */ 84 | //@{ 85 | PseudoModem(const PString &_tty) : ttyname(_tty), valid(FALSE) {}; 86 | //@} 87 | 88 | /**@name Operations */ 89 | virtual PBoolean IsReady() const = 0; 90 | virtual PBoolean CheckRoute(const PString &number) const = 0; 91 | virtual PBoolean Request(PStringToString &request) const = 0; 92 | virtual T38Engine *NewPtrT38Engine() const = 0; 93 | virtual EngineBase *NewPtrUserInputEngine() const = 0; 94 | 95 | const PString &ttyName() const { return ttyname; } 96 | const PString &ptyName() const { return ptyname; } 97 | const PString &modemToken() const { return ptyname; } 98 | PBoolean IsValid() const { return valid; } 99 | //@} 100 | 101 | protected: 102 | Comparison Compare(const PObject & obj) const; 103 | 104 | PString ttyname; 105 | PString ptyname; 106 | PBoolean valid; 107 | }; 108 | /////////////////////////////////////////////////////////////// 109 | class PseudoModemList; 110 | PQUEUE(_PseudoModemQ, PseudoModem); 111 | 112 | class PseudoModemQ : protected _PseudoModemQ 113 | { 114 | PCLASSINFO(PseudoModemQ, _PseudoModemQ); 115 | public: 116 | /**@name Construction */ 117 | //@{ 118 | PseudoModemQ(); 119 | ~PseudoModemQ(); 120 | //@} 121 | 122 | /**@name Operations */ 123 | PBoolean CreateModem( 124 | const PString &tty, 125 | const PString &route, 126 | const PConfigArgs &args, 127 | const PNotifier &callbackEndPoint 128 | ); 129 | void Enqueue(PseudoModem *modem); 130 | PBoolean Enqueue(const PString &modemToken); 131 | PseudoModem *DequeueWithRoute(const PString &number); 132 | PseudoModem *Dequeue(const PString &modemToken); 133 | //@} 134 | protected: 135 | PseudoModem *Find(const PString &modemToken) const; 136 | 137 | PseudoModemList *pmodem_list; 138 | PMutex Mutex; 139 | }; 140 | /////////////////////////////////////////////////////////////// 141 | 142 | #endif // _PMODEM_H 143 | 144 | -------------------------------------------------------------------------------- /dle.cxx: -------------------------------------------------------------------------------- 1 | /* 2 | * dle.cxx 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2001-2008 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): Equivalence Pty ltd 25 | * 26 | * $Log: dle.cxx,v $ 27 | * Revision 1.11 2008-09-10 11:15:00 frolov 28 | * Ported to OPAL SVN trunk 29 | * 30 | * Revision 1.11 2008/09/10 11:15:00 frolov 31 | * Ported to OPAL SVN trunk 32 | * 33 | * Revision 1.10 2007/03/23 09:48:23 vfrolov 34 | * Added deleting DLE shielded codes 35 | * 36 | * Revision 1.9 2007/03/22 16:26:04 vfrolov 37 | * Fixed compiler warnings 38 | * 39 | * Revision 1.8 2004/10/27 13:18:03 vfrolov 40 | * Fixed compiler warning 41 | * 42 | * Revision 1.7 2004/10/22 13:34:20 vfrolov 43 | * Fixed buffer overflow 44 | * 45 | * Revision 1.6 2004/07/06 16:07:24 vfrolov 46 | * Included ptlib.h for precompiling 47 | * 48 | * Revision 1.5 2003/12/04 13:22:22 vfrolov 49 | * Removed ambiguous isEof() 50 | * Improved memory usage in DataStream 51 | * Fixed myPTRACE 52 | * 53 | * Revision 1.4 2003/01/08 16:37:22 vfrolov 54 | * Changed class DataStream: 55 | * members moved to private section and added isEof() 56 | * added threshold and isFull() 57 | * 58 | * Revision 1.3 2002/04/19 14:29:26 vfrolov 59 | * Added Copyright header 60 | * 61 | * Revision 1.2 2002/01/10 06:10:02 craigs 62 | * Added MPL header 63 | * 64 | * 65 | * Revision 1.1 2002/01/01 23:06:54 craigs 66 | * Initial version 67 | * 68 | */ 69 | 70 | #include 71 | #include "dle.h" 72 | 73 | /////////////////////////////////////////////////////////////// 74 | 75 | #define new PNEW 76 | 77 | /////////////////////////////////////////////////////////////// 78 | static BYTE BitRevTable[256]; 79 | 80 | static PBoolean initBitRevTable() 81 | { 82 | for( unsigned i = 0 ; i < sizeof(BitRevTable) ; i++ ) { 83 | unsigned in = i, out = 0; 84 | for( int j = 0 ; j < 8 ; j++ ) { 85 | out <<= 1; 86 | out += in & 1; 87 | in >>= 1; 88 | } 89 | BitRevTable[i] = (BYTE)out; 90 | } 91 | return TRUE; 92 | } 93 | 94 | static const PBoolean ___InitBitRevTable = initBitRevTable(); 95 | /////////////////////////////////////////////////////////////// 96 | enum { 97 | ETX = 0x03, 98 | DLE = 0x10, 99 | }; 100 | /////////////////////////////////////////////////////////////// 101 | int DLEData::PutDleData(const void *pBuf, PINDEX count) 102 | { 103 | if (PutData(NULL, 0) < 0) 104 | return -1; 105 | 106 | PINDEX cRest = count; 107 | const BYTE *p = (const BYTE *)pBuf; 108 | 109 | while( cRest > 0 ) { 110 | const BYTE *pScan = p; 111 | PINDEX cScan = cRest; 112 | 113 | if (dle) { 114 | dle = FALSE; 115 | if (*p != DLE) { 116 | if (*p == ETX) { 117 | PutEof(); 118 | cRest--; 119 | break; 120 | } 121 | 122 | p++; 123 | cRest--; 124 | } 125 | pScan++; 126 | cScan--; 127 | } 128 | 129 | const BYTE *pDle = (const BYTE *)memchr(pScan, DLE, cScan); 130 | 131 | PINDEX cPut; 132 | PINDEX cDone; 133 | 134 | if( pDle ) { 135 | dle = TRUE; 136 | cPut = PINDEX(pDle - p); 137 | cDone = cPut + 1; // skip DLE 138 | } else { 139 | cDone = cPut = cRest; 140 | } 141 | 142 | if( cPut ) { 143 | if( bitRev ) { 144 | BYTE tmp[1024]; 145 | while( cPut ) { 146 | PINDEX cTmp = cPut > 1024 ? 1024 : cPut; 147 | for( PINDEX i = 0 ; i < cTmp ; i++ ) { 148 | tmp[i] = BitRevTable[p[i]]; 149 | } 150 | PutData(tmp, cTmp); 151 | cPut -= cTmp; 152 | } 153 | } else { 154 | PutData(p, cPut); 155 | } 156 | } 157 | p += cDone; 158 | cRest -= cDone; 159 | } 160 | 161 | return count - cRest; 162 | } 163 | 164 | int DLEData::GetDleData(void *pBuf, PINDEX count) 165 | { 166 | if (recvEtx) 167 | return -1; 168 | 169 | BYTE *p = (BYTE *)pBuf; 170 | int done; 171 | 172 | for (done = 0 ; (count - done) >= 4 ; done = int(p - (BYTE *)pBuf)) { 173 | PINDEX cGet = (count - done - 2) / 2; 174 | BYTE tmp[1024]; 175 | 176 | if (cGet > (PINDEX)sizeof(tmp)) 177 | cGet = sizeof(tmp); 178 | 179 | switch( cGet = GetData(tmp, cGet) ) { 180 | case -1: 181 | *p++ = DLE; 182 | *p++ = ETX; 183 | recvEtx = TRUE; 184 | return int(p - (BYTE *)pBuf); 185 | case 0: 186 | return int(p - (BYTE *)pBuf); 187 | default: 188 | for( PINDEX i = 0 ; i < cGet ; i++ ) { 189 | BYTE b = bitRev ? BitRevTable[tmp[i]] : tmp[i]; 190 | if( b == DLE ) 191 | *p++ = DLE; 192 | *p++ = b; 193 | } 194 | } 195 | } 196 | return done; 197 | } 198 | /////////////////////////////////////////////////////////////// 199 | 200 | -------------------------------------------------------------------------------- /drivers.cxx: -------------------------------------------------------------------------------- 1 | /* 2 | * drivers.cxx 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2004-2008 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): 25 | * 26 | * $Log: drivers.cxx,v $ 27 | * Revision 1.4 2008-09-10 11:15:00 frolov 28 | * Ported to OPAL SVN trunk 29 | * 30 | * Revision 1.4 2008/09/10 11:15:00 frolov 31 | * Ported to OPAL SVN trunk 32 | * 33 | * Revision 1.3 2007/01/29 12:44:41 vfrolov 34 | * Added ability to put args to drivers 35 | * 36 | * Revision 1.2 2004/07/07 13:45:17 vfrolov 37 | * Added C0C driver for Windows 38 | * 39 | * Revision 1.1 2004/07/07 12:38:32 vfrolov 40 | * The code for pseudo-tty (pty) devices that communicates with fax application formed to PTY driver. 41 | * 42 | */ 43 | 44 | #include 45 | #include "pmodemi.h" 46 | #include "drivers.h" 47 | #include "drv_pty.h" 48 | #include "drv_c0c.h" 49 | 50 | /////////////////////////////////////////////////////////////// 51 | 52 | #define new PNEW 53 | 54 | /////////////////////////////////////////////////////////////// 55 | 56 | static int numDrivers = 0; 57 | 58 | /////////////////////////////////////////////////////////////// 59 | #define MAX_DRIVERS 10 60 | 61 | static struct { 62 | const char *name; 63 | PBoolean (*CheckTty)( 64 | const PString &_tty 65 | ); 66 | PString (*ArgSpec)(); 67 | PStringArray (*Description)(); 68 | PseudoModem *(*CreatePseudoModem)( 69 | const PString &tty, 70 | const PString &route, 71 | const PConfigArgs &args, 72 | const PNotifier &callbackEndPoint 73 | ); 74 | } drivers[MAX_DRIVERS]; 75 | 76 | static int addDriver( 77 | const char *name, 78 | PBoolean (*CheckTty)( 79 | const PString &_tty 80 | ), 81 | PString (*ArgSpec)(), 82 | PStringArray (*Description)(), 83 | PseudoModem *(*CreatePseudoModem)( 84 | const PString &tty, 85 | const PString &route, 86 | const PConfigArgs &args, 87 | const PNotifier &callbackEndPoint 88 | ) 89 | ) 90 | { 91 | if (numDrivers >= MAX_DRIVERS) 92 | return -1; 93 | 94 | drivers[numDrivers].name = name; 95 | drivers[numDrivers].CheckTty = CheckTty; 96 | drivers[numDrivers].ArgSpec = ArgSpec; 97 | drivers[numDrivers].Description = Description; 98 | drivers[numDrivers].CreatePseudoModem = CreatePseudoModem; 99 | return numDrivers++; 100 | } 101 | 102 | /////////////////////////////////////////////////////////////// 103 | #define DECLARE_MODEM_DRIVER(name, suffix) \ 104 | static PseudoModem *CreatePseudoModem##suffix( \ 105 | const PString &tty, \ 106 | const PString &route, \ 107 | const PConfigArgs &args, \ 108 | const PNotifier &callbackEndPoint) \ 109 | { \ 110 | return new \ 111 | PseudoModem##suffix(tty, route, args, callbackEndPoint);\ 112 | } \ 113 | static const int ___addDriver##suffix = addDriver( \ 114 | name, \ 115 | &PseudoModem##suffix::CheckTty, \ 116 | &PseudoModem##suffix::ArgSpec, \ 117 | &PseudoModem##suffix::Description, \ 118 | &CreatePseudoModem##suffix \ 119 | ); \ 120 | 121 | /////////////////////////////////////////////////////////////// 122 | #ifdef MODEM_DRIVER_Pty 123 | DECLARE_MODEM_DRIVER("PTY", Pty) 124 | #endif 125 | #ifdef MODEM_DRIVER_C0C 126 | DECLARE_MODEM_DRIVER("C0C", C0C) 127 | #endif 128 | /////////////////////////////////////////////////////////////// 129 | PseudoModem *PseudoModemDrivers::CreateModem( 130 | const PString &tty, 131 | const PString &route, 132 | const PConfigArgs &args, 133 | const PNotifier &callbackEndPoint 134 | ) 135 | { 136 | PseudoModem *modem = NULL; 137 | 138 | for (int i = 0 ; i < numDrivers ; i++) { 139 | if (drivers[i].CheckTty(tty)) { 140 | modem = drivers[i].CreatePseudoModem(tty, route, args, callbackEndPoint); 141 | 142 | if (!modem) { 143 | //myPTRACE(1, "T38Modem\tPseudoModemDrivers::CreateModem " << tty << " was not created"); 144 | return NULL; 145 | } 146 | break; 147 | } 148 | } 149 | 150 | if (!modem) { 151 | //myPTRACE(1, "T38Modem\tPseudoModemDrivers::CreateModem " << tty << " is not a valid value"); 152 | return NULL; 153 | } 154 | 155 | if (!modem->IsValid()) { 156 | //myPTRACE(1, "T38Modem\tPseudoModemDrivers::CreateModem " << tty << " is not valid"); 157 | delete modem; 158 | return NULL; 159 | } 160 | 161 | return modem; 162 | } 163 | 164 | PString PseudoModemDrivers::ArgSpec() 165 | { 166 | PString argSpec; 167 | 168 | for (int i = 0 ; i < numDrivers ; i++) 169 | argSpec += drivers[i].ArgSpec(); 170 | 171 | return argSpec; 172 | } 173 | 174 | PStringArray PseudoModemDrivers::Descriptions() 175 | { 176 | PStringArray descriptions; 177 | 178 | for (int i = 0 ; i < numDrivers ; i++) { 179 | descriptions.Append(new PString(drivers[i].name)); 180 | 181 | PStringArray description = drivers[i].Description(); 182 | 183 | for (PINDEX j = 0 ; j < description.GetSize() ; j++) 184 | descriptions.Append(new PString(PString(" ") + description[j])); 185 | } 186 | 187 | return descriptions; 188 | } 189 | /////////////////////////////////////////////////////////////// 190 | 191 | -------------------------------------------------------------------------------- /tone_gen.cxx: -------------------------------------------------------------------------------- 1 | /* 2 | * tone_gen.cxx 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2010 Vyacheslav Frolov 7 | * 8 | * t38modem Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is t38modem. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): 25 | * 26 | * $Log: tone_gen.cxx,v $ 27 | * Revision 1.1 2010-10-12 16:43:00 vfrolov 28 | * Initial revision 29 | * 30 | * Revision 1.1 2010/10/12 16:43:00 vfrolov 31 | * Initial revision 32 | * 33 | */ 34 | 35 | #include 36 | #include 37 | #include "pmutils.h" 38 | #include "tone_gen.h" 39 | 40 | /////////////////////////////////////////////////////////////// 41 | 42 | #define new PNEW 43 | 44 | /////////////////////////////////////////////////////////////// 45 | #define CNG_HZ 1100 46 | #define CNG_MAX_DIV 100 47 | #define CNG_AMPLITUDE 5000 48 | #define CNG_ON_MSEC 500 49 | #define CNG_OFF_MSEC 3000 50 | /////////////////////////////////////////////////////////////// 51 | #define CED_HZ 2100 52 | #define CED_MAX_DIV 100 53 | #define CED_AMPLITUDE 5000 54 | #define CED_ON_MSEC 3500 55 | /////////////////////////////////////////////////////////////// 56 | #define RING_RU_HZ 425 57 | #define RING_RU_MAX_DIV 25 58 | #define RING_RU_AMPLITUDE 5000 59 | #define RING_RU_ON_MSEC 1000 60 | #define RING_RU_OFF_MSEC 4000 61 | /////////////////////////////////////////////////////////////// 62 | #define BUSY_RU_HZ 425 63 | #define BUSY_RU_MAX_DIV 25 64 | #define BUSY_RU_AMPLITUDE 5000 65 | #define BUSY_RU_ON_MSEC 350 66 | #define BUSY_RU_OFF_MSEC 350 67 | /////////////////////////////////////////////////////////////// 68 | typedef PInt16 SIMPLE_TYPE; 69 | #define BYTES_PER_SIMPLE sizeof(SIMPLE_TYPE) 70 | #define SIMPLES_PER_SEC 8000 71 | /////////////////////////////////////////////////////////////// 72 | #define TWO_PI (3.1415926535897932384626433832795029L*2) 73 | 74 | static PBoolean InitTone(const void *, BYTE *pTone, size_t amount, unsigned hz, SIMPLE_TYPE ampl) 75 | { 76 | for( size_t i = 0 ; i < amount/BYTES_PER_SIMPLE ; i++ ) { 77 | double Sin = sin(double((hz*TWO_PI*i)/SIMPLES_PER_SEC)); 78 | ((SIMPLE_TYPE *)pTone)[i] = (SIMPLE_TYPE)(Sin * ampl); 79 | } 80 | 81 | return TRUE; 82 | } 83 | /////////////////////////////////////////////////////////////// 84 | #define MSEC2BYTES(ms) (((SIMPLES_PER_SEC*(ms))/1000)*BYTES_PER_SIMPLE) 85 | #define MAX_DIV2BYTES(maxdiv) ((SIMPLES_PER_SEC/(maxdiv))*BYTES_PER_SIMPLE) 86 | /////////////////////////////////////////////////////////////// 87 | ToneGenerator::ToneGenerator(ToneGenerator::ToneType tt) 88 | : type(tt) 89 | , index(0) 90 | { 91 | switch(tt) { 92 | case ttCng: { 93 | static BYTE toneOn[MAX_DIV2BYTES(CNG_MAX_DIV)]; 94 | static const PBoolean initTone = InitTone(&initTone, toneOn, sizeof(toneOn), CNG_HZ, CNG_AMPLITUDE); 95 | 96 | bytesOn = MSEC2BYTES(CNG_ON_MSEC); 97 | bytesOff = MSEC2BYTES(CNG_OFF_MSEC); 98 | pToneOn = toneOn; 99 | bytesToneOn = sizeof(toneOn); 100 | 101 | // begin with 1 sec silence 102 | #if CNG_OFF_MSEC < 1000 103 | #error CNG_OFF_MSEC < 1000 104 | #endif 105 | index = bytesOn + bytesOff - MSEC2BYTES(1000); 106 | break; 107 | } 108 | case ttCed: { 109 | static BYTE toneOn[MAX_DIV2BYTES(CED_MAX_DIV)]; 110 | static const PBoolean initTone = InitTone(&initTone, toneOn, sizeof(toneOn), CED_HZ, CED_AMPLITUDE); 111 | 112 | bytesOn = MSEC2BYTES(CED_ON_MSEC); 113 | bytesOff = (P_MAX_INDEX/BYTES_PER_SIMPLE)*BYTES_PER_SIMPLE - bytesOn; 114 | pToneOn = toneOn; 115 | bytesToneOn = sizeof(toneOn); 116 | 117 | // begin with 200 ms silence 118 | index = bytesOn + bytesOff - MSEC2BYTES(200); 119 | break; 120 | } 121 | case ttRing: { 122 | static BYTE toneOn[MAX_DIV2BYTES(RING_RU_MAX_DIV)]; 123 | static const PBoolean initTone = InitTone(&initTone, toneOn, sizeof(toneOn), RING_RU_HZ, RING_RU_AMPLITUDE); 124 | 125 | bytesOn = MSEC2BYTES(RING_RU_ON_MSEC); 126 | bytesOff = MSEC2BYTES(RING_RU_OFF_MSEC); 127 | pToneOn = toneOn; 128 | bytesToneOn = sizeof(toneOn); 129 | break; 130 | } 131 | case ttBusy: { 132 | static BYTE toneOn[MAX_DIV2BYTES(BUSY_RU_MAX_DIV)]; 133 | static const PBoolean initTone = InitTone(&initTone, toneOn, sizeof(toneOn), BUSY_RU_HZ, BUSY_RU_AMPLITUDE); 134 | 135 | bytesOn = MSEC2BYTES(BUSY_RU_ON_MSEC); 136 | bytesOff = MSEC2BYTES(BUSY_RU_OFF_MSEC); 137 | pToneOn = toneOn; 138 | bytesToneOn = sizeof(toneOn); 139 | break; 140 | } 141 | default: 142 | bytesOn = 0; 143 | bytesOff = (P_MAX_INDEX/BYTES_PER_SIMPLE)*BYTES_PER_SIMPLE - bytesOn; 144 | pToneOn = NULL; 145 | bytesToneOn = 0; 146 | } 147 | } 148 | 149 | void ToneGenerator::Read(void * buffer, PINDEX amount) 150 | { 151 | BYTE *pBuf = (BYTE *)buffer; 152 | PINDEX bytesOnOff = bytesOn + bytesOff; 153 | 154 | while(amount) { 155 | if (index >= bytesOnOff) 156 | index = 0; 157 | 158 | PINDEX len; 159 | 160 | if (bytesOn > index) { 161 | PINDEX i = index % bytesToneOn; 162 | 163 | len = bytesToneOn - i; 164 | 165 | if (len > amount) 166 | len = amount; 167 | 168 | memcpy(pBuf, pToneOn + i, len); 169 | } else { 170 | len = bytesOnOff - index; 171 | 172 | if (len > amount) 173 | len = amount; 174 | 175 | memset(pBuf, 0, len); 176 | } 177 | 178 | pBuf += len; 179 | amount -= len; 180 | index += len; 181 | } 182 | } 183 | /////////////////////////////////////////////////////////////// 184 | 185 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile 3 | # 4 | # T38FAX Pseudo Modem 5 | # 6 | # Copyright (c) 2001-2011 Vyacheslav Frolov 7 | # 8 | # t38modem Project 9 | # 10 | # The contents of this file are subject to the Mozilla Public License 11 | # Version 1.0 (the "License"); you may not use this file except in 12 | # compliance with the License. You may obtain a copy of the License at 13 | # http://www.mozilla.org/MPL/ 14 | # 15 | # Software distributed under the License is distributed on an "AS IS" 16 | # basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | # the License for the specific language governing rights and limitations 18 | # under the License. 19 | # 20 | # The Original Code is Open H323 Library. 21 | # 22 | # The Initial Developer of the Original Code is Vyacheslav Frolov 23 | # 24 | # Contributor(s): Equivalence Pty ltd 25 | # 26 | # $Log: Makefile,v $ 27 | # Revision 1.29 2011-01-12 12:23:43 vfrolov 28 | # Replaced hardcoded workaround for mgetty-voice by conditional one 29 | # 30 | # Revision 1.29 2011/01/12 12:23:43 vfrolov 31 | # Replaced hardcoded workaround for mgetty-voice by conditional one 32 | # 33 | # Revision 1.28 2010/10/12 16:46:25 vfrolov 34 | # Implemented fake streams 35 | # 36 | # Revision 1.27 2010/10/06 16:54:19 vfrolov 37 | # Redesigned engine opening/closing 38 | # 39 | # Revision 1.26 2010/02/12 08:35:51 vfrolov 40 | # Added fake_codecs.cxx 41 | # 42 | # Revision 1.25 2009/07/31 17:34:40 vfrolov 43 | # Removed --h323-old-asn and --sip-old-asn options 44 | # 45 | # Revision 1.24 2009/07/29 10:39:04 vfrolov 46 | # Moved h323lib specific code to h323lib directory 47 | # 48 | # Revision 1.23 2009/07/27 16:21:24 vfrolov 49 | # Moved h323lib specific code to h323lib directory 50 | # 51 | # Revision 1.22 2008/09/11 16:10:54 frolov 52 | # Ported to H323 Plus trunk 53 | # 54 | # Revision 1.21 2008/09/10 13:39:41 frolov 55 | # Fixed OBJDIR_SUFFIX for OPAL 56 | # 57 | # Revision 1.20 2008/09/10 11:15:00 frolov 58 | # Ported to OPAL SVN trunk 59 | # 60 | # Revision 1.19 2007/07/20 14:28:38 vfrolov 61 | # Added opalutils.cxx 62 | # 63 | # Revision 1.18 2007/07/17 10:03:22 vfrolov 64 | # Added Unix98 PTY support 65 | # 66 | # Revision 1.17 2007/05/28 12:52:27 vfrolov 67 | # Added OPAL support 68 | # 69 | # Revision 1.16 2007/05/17 08:32:44 vfrolov 70 | # Moved class T38Modem from main.h and main.cxx to main_process.cxx 71 | # 72 | # Revision 1.15 2007/05/03 09:21:47 vfrolov 73 | # Added compile time optimization for original ASN.1 sequence 74 | # in T.38 (06/98) Annex A or for CORRIGENDUM No. 1 fix 75 | # 76 | # Revision 1.14 2007/03/23 10:14:35 vfrolov 77 | # Implemented voice mode functionality 78 | # 79 | # Revision 1.13 2006/10/20 10:06:43 vfrolov 80 | # Added REPEAT_INDICATOR_SENDING ifdef 81 | # 82 | # Revision 1.12 2006/10/19 10:45:59 vfrolov 83 | # Added FD_TRACE_LEVEL ifdef 84 | # 85 | # Revision 1.11 2004/07/07 12:38:32 vfrolov 86 | # The code for pseudo-tty (pty) devices that communicates with fax application formed to PTY driver. 87 | # 88 | # Revision 1.10 2004/03/09 17:22:58 vfrolov 89 | # Added PROCESS_PER_THREAD ifdef 90 | # 91 | # Revision 1.9 2003/12/04 15:56:45 vfrolov 92 | # Added hdlc.cxx t30.cxx fcs.cxx 93 | # 94 | # Revision 1.8 2002/08/05 10:10:29 robertj 95 | # Normalised Makefile usage of openh323u.mak include file, fixing odd messages. 96 | # 97 | # Revision 1.7 2002/04/30 11:05:17 vfrolov 98 | # Implemented T.30 Calling Tone (CNG) generation 99 | # 100 | # Revision 1.6 2002/04/30 03:52:28 craigs 101 | # Added option for G.723.1 codec 102 | # 103 | # Revision 1.5 2002/04/27 10:17:20 vfrolov 104 | # Added checking if COUT_TRACE or MYPTRACE_LEVEL defined 105 | # Do not add -DCOUT_TRACE by default 106 | # 107 | # Revision 1.4 2002/02/11 08:35:08 vfrolov 108 | # myPTRACE() outputs trace to cout only if defined COUT_TRACE 109 | # 110 | # Revision 1.3 2002/01/10 06:10:02 craigs 111 | # Added MPL header 112 | # 113 | # 114 | 115 | %.o: %.cxx 116 | $(CXX) -c $(CFLAGS) $(CPPFLAGS) -o $@ $< 117 | 118 | PROG = t38modem 119 | OBJECTS := pmutils.o dle.o pmodem.o pmodemi.o drivers.o \ 120 | t30.o hdlc.o fcs.o \ 121 | pmodeme.o enginebase.o t38engine.o \ 122 | drv_pty.o \ 123 | opal/opalutils.o \ 124 | opal/modemep.o opal/modemstrm.o \ 125 | opal/h323ep.o \ 126 | opal/sipep.o \ 127 | opal/manager.o 128 | 129 | CPPFLAGS += `pkg-config --cflags opal` 130 | LDFLAGS += `pkg-config --libs opal` 131 | 132 | # 133 | # If defined COUT_TRACE then enable duplicate the 134 | # output of myPTRACE() to cout 135 | # 136 | ifdef COUT_TRACE 137 | CPPFLAGS += -DCOUT_TRACE 138 | endif 139 | 140 | # 141 | # By default the code will be optimized for original ASN.1 142 | # sequence in T.38 (06/98) Annex A (it's optimal if you use 143 | # --old-asn option). 144 | # If defined OPTIMIZE_CORRIGENDUM_IFP then the code will be 145 | # optimized for CORRIGENDUM No. 1 fix (it's optimal if you 146 | # do not use --old-asn option). 147 | # 148 | ifdef OPTIMIZE_CORRIGENDUM_IFP 149 | CPPFLAGS += -DOPTIMIZE_CORRIGENDUM_IFP 150 | endif 151 | 152 | # 153 | # If defined MYPTRACE_LEVEL=N then myPTRACE() will 154 | # output the trace with level N 155 | # 156 | ifdef MYPTRACE_LEVEL 157 | CPPFLAGS += -DMYPTRACE_LEVEL=$(MYPTRACE_LEVEL) 158 | endif 159 | 160 | # 161 | # If defined FD_TRACE_LEVEL=N then myPTRACE() will 162 | # output the warnings on level N for big file descriptors 163 | # 164 | ifdef FD_TRACE_LEVEL 165 | CPPFLAGS += -DFD_TRACE_LEVEL=$(FD_TRACE_LEVEL) 166 | endif 167 | 168 | # 169 | # If defined PROCESS_PER_THREAD then 170 | # - PID will be used in thread name rather then TID 171 | # - CPU usage will be traced 172 | # 173 | ifdef PROCESS_PER_THREAD 174 | CPPFLAGS += -DPROCESS_PER_THREAD 175 | endif 176 | 177 | # 178 | # If defined REPEAT_INDICATOR_SENDING then t38modem 179 | # will repeat indicator sending on idle 180 | # 181 | ifdef REPEAT_INDICATOR_SENDING 182 | CPPFLAGS += -DREPEAT_INDICATOR_SENDING 183 | endif 184 | 185 | # 186 | # If defined USE_LEGACY_PTY then t38modem will use 187 | # legacy scheme for pty devices. 188 | # If defined USE_UNIX98_PTY or not defined USE_LEGACY_PTY 189 | # then t38modem will use Unix98 scheme for pty devices. 190 | # Both schemes cen be used simultaneously. 191 | # 192 | ifdef USE_LEGACY_PTY 193 | CPPFLAGS += -DUSE_LEGACY_PTY 194 | 195 | ifdef USE_UNIX98_PTY 196 | CPPFLAGS += -DUSE_UNIX98_PTY 197 | endif 198 | else 199 | CPPFLAGS += -DUSE_UNIX98_PTY 200 | endif 201 | 202 | # 203 | # If defined ALAW_132_BIT_REVERSE then t38modem 204 | # will use reversed bit order for +VSM=132 205 | # (workaround for mgetty-voice) 206 | # 207 | ifdef ALAW_132_BIT_REVERSE 208 | CPPFLAGS += -DALAW_132_BIT_REVERSE 209 | endif 210 | 211 | .PHONY: all clean 212 | all: $(PROG) 213 | 214 | clean: 215 | rm -f $(PROG) $(OBJECTS) 216 | 217 | $(PROG) : $(OBJECTS) 218 | $(CXX) $(CPPFLAGS) -o $(PROG) $(OBJECTS) $(LDFLAGS) 219 | -------------------------------------------------------------------------------- /pmodem.cxx: -------------------------------------------------------------------------------- 1 | /* 2 | * pmodem.cxx 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2001-2008 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): Equivalence Pty ltd 25 | * 26 | * $Log: pmodem.cxx,v $ 27 | * Revision 1.11 2008-09-10 11:15:00 frolov 28 | * Ported to OPAL SVN trunk 29 | * 30 | * Revision 1.11 2008/09/10 11:15:00 frolov 31 | * Ported to OPAL SVN trunk 32 | * 33 | * Revision 1.10 2007/03/22 16:26:04 vfrolov 34 | * Fixed compiler warnings 35 | * 36 | * Revision 1.9 2007/01/29 12:44:41 vfrolov 37 | * Added ability to put args to drivers 38 | * 39 | * Revision 1.8 2006/05/23 14:48:54 vfrolov 40 | * Fixed race condition (reported by Tamas) 41 | * 42 | * Revision 1.7 2004/07/07 12:38:32 vfrolov 43 | * The code for pseudo-tty (pty) devices that communicates with fax application formed to PTY driver. 44 | * 45 | * Revision 1.6 2004/05/09 07:46:11 csoutheren 46 | * Updated to compile with new PIsDescendant function 47 | * 48 | * Revision 1.5 2002/05/15 16:17:44 vfrolov 49 | * Implemented per modem routing for I/C calls 50 | * 51 | * Revision 1.4 2002/03/05 12:35:52 vfrolov 52 | * Added Copyright header 53 | * Changed class hierarchy 54 | * PseudoModem is abstract 55 | * PseudoModemBody is child of PseudoModem 56 | * Added PseudoModemQ::CreateModem() to create instances 57 | * Some OS specific code moved from pmodem.cxx to pty.cxx 58 | * 59 | * Revision 1.3 2002/02/08 12:58:22 vfrolov 60 | * Defined Linux and FreeBSD patterns in ttyPattern(). 61 | * 62 | * Revision 1.2 2002/01/10 06:10:02 craigs 63 | * Added MPL header 64 | * 65 | * Revision 1.1 2002/01/01 23:06:54 craigs 66 | * Initial version 67 | * 68 | */ 69 | 70 | #include 71 | #include "pmodem.h" 72 | #include "drivers.h" 73 | 74 | #define new PNEW 75 | 76 | /////////////////////////////////////////////////////////////// 77 | PLIST(_PseudoModemList, PseudoModem); 78 | 79 | class PseudoModemList : protected _PseudoModemList 80 | { 81 | PCLASSINFO(PseudoModemList, _PseudoModemList); 82 | public: 83 | PINDEX Append(PseudoModem *modem); 84 | PseudoModem *Find(const PString &modemToken) const; 85 | protected: 86 | PseudoModem *_Find(const PString &modemToken) const; 87 | PMutex Mutex; 88 | }; 89 | 90 | PINDEX PseudoModemList::Append(PseudoModem *modem) 91 | { 92 | PWaitAndSignal mutexWait(Mutex); 93 | 94 | if (_Find(modem->modemToken())) { 95 | myPTRACE(1, "T38Modem\tPseudoModemList::Append can't add " << modem->ptyName() << " to modem list"); 96 | delete modem; 97 | return P_MAX_INDEX; 98 | } 99 | 100 | PINDEX i = _PseudoModemList::Append(modem); 101 | 102 | myPTRACE(3, "T38Modem\tPseudoModemList::Append " << modem->ptyName() << " (" << i << ") OK"); 103 | 104 | return i; 105 | } 106 | 107 | PseudoModem *PseudoModemList::Find(const PString &modemToken) const 108 | { 109 | PWaitAndSignal mutexWait(Mutex); 110 | return _Find(modemToken); 111 | } 112 | 113 | PseudoModem *PseudoModemList::_Find(const PString &modemToken) const 114 | { 115 | PObject *object; 116 | 117 | for (PINDEX i = 0 ; (object = ((PCollection*)this)->GetAt(i)) != NULL ; i++) { 118 | PAssert(PIsDescendant(object, PseudoModem), PInvalidCast); 119 | PseudoModem *modem = (PseudoModem *)object; 120 | if (modem->modemToken() == modemToken) 121 | return modem; 122 | } 123 | return NULL; 124 | } 125 | /////////////////////////////////////////////////////////////// 126 | PObject::Comparison PseudoModem::Compare(const PObject & obj) const 127 | { 128 | PAssert(PIsDescendant(&obj, PseudoModem), PInvalidCast); 129 | const PseudoModem & other = (const PseudoModem &)obj; 130 | return modemToken().Compare(other.modemToken()); 131 | } 132 | /////////////////////////////////////////////////////////////// 133 | PseudoModemQ::PseudoModemQ() 134 | { 135 | pmodem_list = new PseudoModemList(); 136 | } 137 | 138 | PseudoModemQ::~PseudoModemQ() 139 | { 140 | delete pmodem_list; 141 | } 142 | 143 | PBoolean PseudoModemQ::CreateModem( 144 | const PString &tty, 145 | const PString &route, 146 | const PConfigArgs &args, 147 | const PNotifier &callbackEndPoint 148 | ) 149 | { 150 | PseudoModem *modem = PseudoModemDrivers::CreateModem(tty, route, args, callbackEndPoint); 151 | 152 | if (!modem) 153 | return FALSE; 154 | 155 | if (pmodem_list->Append(modem) == P_MAX_INDEX) 156 | return FALSE; 157 | 158 | modem->Resume(); 159 | 160 | return TRUE; 161 | } 162 | 163 | void PseudoModemQ::Enqueue(PseudoModem *modem) 164 | { 165 | myPTRACE((modem != NULL) ? 3 : 1, "T38Modem\tPseudoModemQ::Enqueue " 166 | << ((modem != NULL) ? modem->ptyName() : "BAD")); 167 | 168 | PWaitAndSignal mutexWait(Mutex); 169 | _PseudoModemQ::Enqueue(modem); 170 | } 171 | 172 | PBoolean PseudoModemQ::Enqueue(const PString &modemToken) 173 | { 174 | PseudoModem *modem = pmodem_list->Find(modemToken); 175 | 176 | if (!modem) { 177 | myPTRACE(1, "T38Modem\tPseudoModemQ::Enqueue BAD token " << modemToken); 178 | return FALSE; 179 | } 180 | 181 | Enqueue(modem); 182 | 183 | return TRUE; 184 | } 185 | 186 | PseudoModem *PseudoModemQ::DequeueWithRoute(const PString &number) 187 | { 188 | PWaitAndSignal mutexWait(Mutex); 189 | PObject *object; 190 | 191 | for( PINDEX i = 0 ; (object = ((PCollection*)this)->GetAt(i)) != NULL ; i++ ) { 192 | PAssert(PIsDescendant(object, PseudoModem), PInvalidCast); 193 | PseudoModem *modem = (PseudoModem *)object; 194 | if (modem->CheckRoute(number) && modem->IsReady()) { 195 | if (!Remove(modem)) 196 | modem = NULL; 197 | myPTRACE(3, "T38Modem\tPseudoModemQ::DequeueWithRoute " 198 | << ((modem != NULL) ? modem->ptyName() : "BAD")); 199 | return modem; 200 | } 201 | } 202 | return NULL; 203 | } 204 | 205 | PseudoModem *PseudoModemQ::Find(const PString &modemToken) const 206 | { 207 | PObject *object; 208 | 209 | for( PINDEX i = 0 ; (object = ((PCollection*)this)->GetAt(i)) != NULL ; i++ ) { 210 | PAssert(PIsDescendant(object, PseudoModem), PInvalidCast); 211 | PseudoModem *modem = (PseudoModem *)object; 212 | if( modem->modemToken() == modemToken ) { 213 | return modem; 214 | } 215 | } 216 | return NULL; 217 | } 218 | 219 | PseudoModem *PseudoModemQ::Dequeue(const PString &modemToken) 220 | { 221 | PWaitAndSignal mutexWait(Mutex); 222 | PseudoModem *modem = Find(modemToken); 223 | if (modem != NULL && !Remove(modem)) 224 | modem = NULL; 225 | myPTRACE(1, "T38Modem\tPseudoModemQ::Dequeue " 226 | << ((modem != NULL) ? modem->ptyName() : "BAD")); 227 | return modem; 228 | } 229 | /////////////////////////////////////////////////////////////// 230 | 231 | -------------------------------------------------------------------------------- /opal/manager.h: -------------------------------------------------------------------------------- 1 | /* 2 | * manager.h 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2007-2010 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): 25 | * 26 | * $Log: manager.h,v $ 27 | * Revision 1.6 2010-03-15 13:40:27 vfrolov 28 | * Removed unused code 29 | * 30 | * Revision 1.6 2010/03/15 13:40:27 vfrolov 31 | * Removed unused code 32 | * 33 | * Revision 1.5 2009/11/10 11:30:57 vfrolov 34 | * Implemented G.711 fallback to fax pass-through mode 35 | * 36 | * Revision 1.4 2009/07/15 13:23:20 vfrolov 37 | * Added Descriptions(args) 38 | * 39 | * Revision 1.3 2009/01/15 08:46:34 vfrolov 40 | * Fixed OnRouteConnection() be able to compile with OPAL trunk since 21925 41 | * 42 | * Revision 1.2 2008/09/10 11:15:00 frolov 43 | * Ported to OPAL SVN trunk 44 | * 45 | * Revision 1.1 2007/05/28 12:47:52 vfrolov 46 | * Initial revision 47 | * 48 | */ 49 | 50 | #ifndef _PM_MANAGER_H 51 | #define _PM_MANAGER_H 52 | 53 | #include 54 | #include "../version.h" 55 | 56 | ///////////////////////////////////////////////////////////////////////////// 57 | /**Create a process for OpalManagerConsole based applications. 58 | */ 59 | template 67 | 68 | class MyManagerProcess : public PProcess 69 | { 70 | PCLASSINFO(MyManagerProcess, PProcess) 71 | public: 72 | MyManagerProcess() 73 | : PProcess(Manuf, Name, MajorVersion, MinorVersion, Status, BuildNumber) 74 | , m_manager(NULL) 75 | { 76 | } 77 | 78 | ~MyManagerProcess() 79 | { 80 | delete this->m_manager; 81 | } 82 | 83 | virtual void Main() 84 | { 85 | this->SetTerminationValue(1); 86 | this->m_manager = new Manager; 87 | if (this->m_manager->Initialise(this->GetArguments(), Verbose)) { 88 | this->SetTerminationValue(0); 89 | this->m_manager->Run(); 90 | } 91 | } 92 | 93 | virtual bool OnInterrupt(bool) 94 | { 95 | if (this->m_manager == NULL) 96 | return false; 97 | 98 | this->m_manager->EndRun(true); 99 | return false; 100 | } 101 | 102 | private: 103 | Manager * m_manager; 104 | }; 105 | 106 | 107 | ///////////////////////////////////////////////////////////////////////////// 108 | 109 | class MyManagerEndPoint; 110 | 111 | class MyManager : public OpalManager 112 | { 113 | PCLASSINFO(MyManager, OpalManager); 114 | 115 | public: 116 | MyManager() 117 | // : m_endpointPrefixes(PConstString(endpointPrefixes).Tokenise(" \t\n")) 118 | : m_interrupted(false) 119 | , m_verbose(false) 120 | , m_outputStream(&cout) 121 | { 122 | } 123 | 124 | virtual PString GetArgumentSpec(); 125 | virtual void Usage(ostream & strm, const PArgList & args); 126 | virtual bool PreInitialise(PArgList & args, bool verbose = false); 127 | virtual bool Initialise(PArgList & args, bool verbose, const PString & defaultRoute = PString::Empty()); 128 | virtual void Run(); 129 | virtual void EndRun(bool interrupt = false); 130 | virtual void Broadcast(const PString & msg); 131 | 132 | virtual bool OnRouteConnection( 133 | PStringSet & routesTried, ///< Set of routes already tried 134 | const PString & a_party, ///< Source local address 135 | const PString & b_party, ///< Destination indicated by source 136 | OpalCall & call, ///< Call for new connection 137 | unsigned options, ///< Options for new connection (can't use default as overrides will fail) 138 | OpalConnection::StringOptions * stringOptions 139 | ); 140 | virtual void OnClearedCall(OpalCall & call); 141 | 142 | virtual PBoolean OnOpenMediaStream(OpalConnection & connection, OpalMediaStream & stream); 143 | virtual void OnClosedMediaStream(const OpalMediaStream & stream); 144 | 145 | virtual PString ApplyRouteTable(const PString & proto, const PString & addr, PINDEX & entry); 146 | 147 | class LockedStream : PWaitAndSignal 148 | { 149 | protected: 150 | ostream & m_stream; 151 | public: 152 | LockedStream(const MyManager & mgr) 153 | : PWaitAndSignal(mgr.m_outputMutex) 154 | , m_stream(*mgr.m_outputStream) 155 | { 156 | } 157 | 158 | ostream & operator *() const { return m_stream; } 159 | operator ostream & () const { return m_stream; } 160 | }; 161 | friend class LockedStream; 162 | __inline LockedStream LockedOutput() const { return *this; } 163 | 164 | protected: 165 | PMutex m_outputMutex; 166 | PSimpleTimer m_competionTimeout; 167 | bool m_showProgress; 168 | PSyncPoint m_endRun; 169 | PStringArray m_endpointPrefixes; 170 | bool m_interrupted; 171 | bool m_verbose; 172 | ostream * m_outputStream; 173 | MyManagerEndPoint * epSIP; 174 | MyManagerEndPoint * epFAX; 175 | }; 176 | ///////////////////////////////////////////////////////////////////////////// 177 | 178 | /**This class allows for each end point class, e.g. SIPEndPoint, to add it's 179 | set of parameters/commands to to the console application. 180 | */ 181 | class MyManagerEndPoint 182 | { 183 | protected: 184 | MyManagerEndPoint(MyManager & manager) : m_mgr(manager) { } 185 | 186 | void AddRoutesFor(const OpalEndPoint * endpoint, const PString & defaultRoute) 187 | { 188 | if (defaultRoute.IsEmpty()) 189 | return; 190 | 191 | PStringList prefixes = m_mgr.GetPrefixNames(endpoint); 192 | 193 | for (PINDEX i = 0; i < prefixes.GetSize(); ++i) 194 | m_mgr.AddRouteEntry(prefixes[i] + ":.* = " + defaultRoute); 195 | } 196 | 197 | 198 | public: 199 | virtual ~MyManagerEndPoint() { } 200 | enum InitResult { 201 | InitFailed, 202 | InitDisabled, 203 | InitSuccess 204 | }; 205 | virtual bool Initialise(PArgList & args, bool verbose, const PString & defaultRoute) = 0; 206 | 207 | protected: 208 | MyManager & m_mgr; 209 | }; 210 | 211 | #endif // _PM_MANAGER_H 212 | 213 | -------------------------------------------------------------------------------- /Changes.txt: -------------------------------------------------------------------------------- 1 | /* 2 | * CHANGES 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Original author: Vyacheslav Frolov 7 | * 8 | */ 9 | 10 | Changelog for t38modem 3.14.0 (Mar 3 2016) 11 | --- Requires Opal 3.10.14 / Ptlib 2.10.14 12 | * Additional debug on SIP Registration. 13 | * New option: --sip-retry-403-forbidden 14 | UNIFY systems will respond 403 Forbidden when resetting to apply new 15 | settings. RFC 3261 says this is a final answer and the request should 16 | not be retried. UNIFY says that is the way they work and you have to 17 | retry. This violates ithe RFC, but is needed to make UNIFY work. 18 | * Added ability to use the all of the Fake Codecs: 19 | G.722, G.722.1, G.722.2, G.726-40K, G.726-32K, G.726-24K, G.726-16K, 20 | G.728, G.729, G.729A, G.729B, G.729A/B, G.723.1, G.723.1(5.3k), 21 | G.723.1A(6.3k), G.723.1A(5.3k), GSM-06.10, GSM-AMR, iLBC 22 | Specify with --fake-audio option and --sip-audio or --h323-audio options. 23 | 24 | Changelog for t38modem 3.13.0 (Aug 10 2015) 25 | --- Requires Opal 3.10.13 / Ptlib 2.10.13 26 | * Opal 3.10.13 changed to fix Cisco CUBE bug where it starts with sequenc 27 | number 32768 instead of the required 0 in UDPTL T.38 packets. 28 | * Added missing DTMF method in SDP on Invite. Fixes some Alcatel systems. 29 | 30 | Changelog for t38modem 3.12.1 (Jan 31 2015) 31 | --- Requires Opal 3.10.12 / Ptlib 2.10.12 32 | * New option: --force-fax-mode-delay 33 | 34 | Changelog for t38modem 3.12.0 (Jan 31 2015) 35 | --- Requires Opal 3.10.12 / Ptlib 2.10.12 36 | * Supports G.711 Passthru mode with the addition of spandsp 0.0.6 plugin. 37 | * Changed port numbers to work on Verszon network. We now use 10000-10999. 38 | 39 | Changelog for t38modem 3.11.0 (Nov 12 2013) 40 | * Changes to work with Opal 3.10.11. 41 | 42 | Changelog for t38modem 2.0.1 (Sep 24 2013) 43 | * Busy Fix (When busy set cause code to EndedByLocalBusy instead of 44 | EndedByLocalUser) 45 | 46 | Changelog for t38modem 2.0.0 (Apr 13 2011) 47 | 48 | * (OPAL) Implemented G.711 fallback to fax pass-through mode. 49 | * (OPAL) Added ability to disable T.38 fax mode. 50 | * (OPAL) Implemented multiple per-route options to override command line 51 | options (NOTE: the route comma delimiter in command line was deprecated 52 | for this reason). 53 | * Added ability to set Q.931 bearer capability information element for 54 | H.323 connections. 55 | * Enabled dialing characters # and * in extension number. 56 | * Replaced hardcoded timeouts by S7 value (V.250). 57 | * (OPAL) Implemented fake audio codecs G.722, G.722.1, G.722.2, 58 | G.723.1, G.723.1(5.3k), G.723.1A(5.3k), G.723.1A(6.3k), G.726-16K, 59 | G.726-24K, G.726-32K, G.726-40K, G.728, G.729, G.729A, G.729A/B, 60 | G.729B, GSM-06.10, GSM-AMR, iLBC. 61 | * (OPAL) Restored and improved ability to set error recovery redundancy for 62 | IFP packets. 63 | * (OPAL) Restored and improved ability to continuously re-send last UDPTL 64 | packet. 65 | * (OPAL) Implemented fallback to alternate route option. 66 | * (OPAL) Added ability to build with OPAL configured to disable H.323 or 67 | SIP protocol support. 68 | * Allowed "+ A B C D" dialing digits in called number. 69 | * Added ignoring unrecognized dialing digits (V.250). 70 | * Implemented dial string terminated by a semicolon ("ATD;[...]"). 71 | * Implemented fake Ring Tone and Busy Tone generation for voice-modem mode. 72 | * Replaced hardcoded workaround for mgetty-voice by conditional-compiling one 73 | (ALAW_132_BIT_REVERSE). 74 | * Added ability to put called number to Caller ID info with NAME or NMBR tags. 75 | * Fixed some other bugs and incompatibilities. Made some other improvements. 76 | Added some other options. 77 | 78 | Changelog for t38modem 1.2.0 (Oct 8 2009) 79 | 80 | * Enabled dialing characters # and *. 81 | * Added ability to dial extension numbers. 82 | * Dial modifiers 'T' and 'P' can be used instead 'D'. 83 | * Fixed incompatibilities with some voice applications (V.253). 84 | * Added ability to dial after call answer. 85 | * Added semicolon concatenating of AT commands. 86 | * Added ability to dial and switch to answering mode ("ATD;A"). 87 | * Fixed incompatibilities with some OS. 88 | * (OPAL) Added ability to use route pattern "modem:.*@tty". 89 | * (OPAL) Added ability to enable/disadle/reorder audio formats. 90 | * (OPAL) Removed --h323-old-asn and --sip-old-asn options. 91 | * Fixed some other bugs. 92 | 93 | Changelog for t38modem 1.1.0 (Apr 16 2009) 94 | 95 | * Fixed 100% CPU usage at the begining of T.38 session. 96 | * Fixed transmission fail with ECM. 97 | * Added H323Plus support. 98 | * Added OPAL v3.6 Lalande support. 99 | * (OPAL) Added STUN support. 100 | * (OPAL) Added ability to set outbound proxy for SIP. 101 | * (OPAL) Added ability to set registrar for SIP. 102 | * (OPAL) options --h323-redundancy, --h323-repeat, --sip-redundancy 103 | and --sip-repeat are disabled (because no support in OPAL). 104 | 105 | Oct 6 2008 - t38modem moved to http://sourceforge.net/projects/t38modem/. 106 | 107 | Changelog for t38modem 1.0.0 (Aug 29 2008) 108 | 109 | * Added OPAL support. 110 | * Implemented voice mode functionality. 111 | * The code optimized for original ASN.1 sequence in T.38 (06/98) 112 | Annex A (it's optimal if you use --old-asn option). Compiling 113 | with OPTIMIZE_CORRIGENDUM_IFP will optimize for CORRIGENDUM No. 1 114 | fix (it's optimal if you do not use --old-asn option). 115 | * Added ability to continuously re-send last UDPTL packet. 116 | * Added Unix98 PTY support. 117 | 118 | Changelog for t38modem 0.8.4 (Mar 22 2007) 119 | 120 | * Fixed incompatibilities with some endpoints. 121 | * Fixed big file descriptors problem. 122 | * Fixed some possible dead locks. 123 | * Implemented AT#HCLR command. 124 | * Added ability to set range of IP ports to use. 125 | 126 | NOTE: To compile t38modem since version 0.8.4 you need 127 | openh323 since version 1.19.1. 128 | 129 | Changelog for t38modem 0.8.3 (Jun 29 2006) 130 | 131 | * Fixed race condition on start up. 132 | * Added -v option to keep Debian packaging happy. 133 | 134 | Changelog for t38modem 0.8.2 (Sep 14 2005) 135 | 136 | * Fixed incompatibilities with some endpoints. 137 | * Fixed UDPTL size. 138 | 139 | Changelog for t38modem 0.8.1 (Mar 31 2005) 140 | 141 | * Fixed incompatibilities with some fax applications. 142 | * Implemented some AT commands. 143 | * Fixed some bugs. 144 | 145 | Changelog for t38modem 0.8.0 (Oct 29 2004) 146 | 147 | * Ported to Windows. 148 | 149 | Changelog for t38modem 0.7.0 (Jul 7 2004) 150 | 151 | * Implemented FCS generation. The DCE transfers FCS octets after 152 | the HDLC data to the DTE (as it should be). 153 | HylaFax Users: the config parameter "Class1FrameOverhead: 2" 154 | should be discarded if it was used. 155 | * Implemented ECM support. 156 | 157 | Jun 2003 - t38modem moved to http://openh323.sourceforge.net/. 158 | Jun 6 2003 - t38modem 0.6.3 released. 159 | Jan 15 2003 - t38modem 0.6.2 released. 160 | Jan 6 2003 - t38modem 0.6.1 released. 161 | Dec 12 2002 - t38modem 0.6.0 released. 162 | Nov 14 2002 - t38modem 0.5.0 released. 163 | Aug 16 2002 - t38modem 0.4.2 released. 164 | Jul 9 2002 - t38modem 0.4.1 released. 165 | Mar 26 2002 - t38modem 0.4.0 released. 166 | Feb 12 2002 - t38modem 0.1.0 released. 167 | Jan 1 2002 - t38modem commited to http://www.openh323.org/. 168 | Dec 2001 - t38modem can send faxes. 169 | Oct 2001 - t38modem can receive faxes. 170 | Sep 2001 - t38modem project started. 171 | -------------------------------------------------------------------------------- /pmutils.cxx: -------------------------------------------------------------------------------- 1 | /* 2 | * pmutils.cxx 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2001-2006 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): Equivalence Pty ltd 25 | * 26 | * $Log: pmutils.cxx,v $ 27 | * Revision 1.13 2006-12-11 10:27:35 vfrolov 28 | * Disabled renaming thread if no PTRACING 29 | * 30 | * Revision 1.13 2006/12/11 10:27:35 vfrolov 31 | * Disabled renaming thread if no PTRACING 32 | * 33 | * Revision 1.12 2005/02/03 11:32:12 vfrolov 34 | * Fixed MSVC compile warnings 35 | * 36 | * Revision 1.11 2004/10/20 14:15:09 vfrolov 37 | * Added reset of signal counter to WaitDataReady() 38 | * 39 | * Revision 1.10 2004/07/06 16:07:24 vfrolov 40 | * Included ptlib.h for precompiling 41 | * 42 | * Revision 1.9 2004/03/09 17:23:11 vfrolov 43 | * Added PROCESS_PER_THREAD ifdef 44 | * 45 | * Revision 1.8 2004/02/17 13:23:14 vfrolov 46 | * Fixed MSVC compile errors 47 | * 48 | * Revision 1.7 2003/12/04 13:22:28 vfrolov 49 | * Removed ambiguous isEof() 50 | * Improved memory usage in DataStream 51 | * Fixed myPTRACE 52 | * 53 | * Revision 1.6 2003/01/08 16:37:25 vfrolov 54 | * Changed class DataStream: 55 | * members moved to private section and added isEof() 56 | * added threshold and isFull() 57 | * 58 | * Revision 1.5 2002/12/30 12:49:36 vfrolov 59 | * Added tracing thread's CPU usage (Linux only) 60 | * 61 | * Revision 1.4 2002/12/20 10:12:57 vfrolov 62 | * Implemented tracing with PID of thread (for LinuxThreads) 63 | * or ID of thread (for other POSIX Threads) 64 | * 65 | * Revision 1.3 2002/03/07 07:55:18 vfrolov 66 | * Fixed endless recursive call SignalChildStop(). Possible there is 67 | * a bug in gcc version 2.95.4 20010902 (Debian prerelease). 68 | * Markus Storm reported the promlem. 69 | * Added Copyright header. 70 | * 71 | * Revision 1.2 2002/01/10 06:10:03 craigs 72 | * Added MPL header 73 | * 74 | * Revision 1.1 2002/01/01 23:06:54 craigs 75 | * Initial version 76 | * 77 | */ 78 | 79 | #include 80 | #include "pmutils.h" 81 | 82 | #define new PNEW 83 | 84 | /////////////////////////////////////////////////////////////// 85 | ModemThread::ModemThread() 86 | : PThread(30000, 87 | NoAutoDeleteThread, 88 | NormalPriority), 89 | stop(FALSE), 90 | childstop(FALSE) 91 | { 92 | } 93 | 94 | void ModemThread::SignalChildStop() { 95 | childstop = TRUE; 96 | SignalDataReady(); 97 | } 98 | 99 | void ModemThread::SignalStop() { 100 | stop = TRUE; 101 | SignalDataReady(); 102 | } 103 | 104 | void ModemThread::WaitDataReady() 105 | { 106 | //do { 107 | dataReadySyncPoint.Wait(); 108 | //} while(!dataReadySyncPoint.WillBlock()); 109 | } 110 | /////////////////////////////////////////////////////////////// 111 | ModemThreadChild::ModemThreadChild(ModemThread &_parent) 112 | : parent(_parent) 113 | { 114 | } 115 | 116 | void ModemThreadChild::SignalStop() 117 | { 118 | ModemThread::SignalStop(); 119 | parent.SignalChildStop(); 120 | } 121 | /////////////////////////////////////////////////////////////// 122 | int ChunkStream::write(const void *pBuf, PINDEX count) 123 | { 124 | int len = sizeof(data) - last; 125 | 126 | if (!len) 127 | return -1; 128 | 129 | if (len > count) 130 | len = count; 131 | 132 | memcpy(data + last, pBuf, len); 133 | last += len; 134 | 135 | return len; 136 | } 137 | 138 | int ChunkStream::read(void *pBuf, PINDEX count) 139 | { 140 | if (sizeof(data) == first) 141 | return -1; 142 | 143 | int len = last - first; 144 | 145 | if (len > count) 146 | len = count; 147 | 148 | memcpy(pBuf, data + first, len); 149 | first += len; 150 | 151 | return len; 152 | } 153 | /////////////////////////////////////////////////////////////// 154 | int DataStream::PutData(const void *_pBuf, PINDEX count) 155 | { 156 | if (eof) 157 | return -1; 158 | 159 | int done = 0; 160 | const BYTE *pBuf = (const BYTE *)_pBuf; 161 | 162 | while (count) { 163 | if (!lastBuf) { 164 | lastBuf = new ChunkStream(); 165 | bufQ.Enqueue(lastBuf); 166 | } 167 | 168 | int len = lastBuf->write(pBuf, count); 169 | 170 | if (len < 0) { 171 | lastBuf = NULL; 172 | } else { 173 | pBuf += len; 174 | count -= len; 175 | done += len; 176 | } 177 | } 178 | 179 | busy += done; 180 | 181 | return done; 182 | } 183 | 184 | int DataStream::GetData(void *_pBuf, PINDEX count) 185 | { 186 | if (!busy) { 187 | if (eof) 188 | return -1; 189 | else 190 | return 0; 191 | } 192 | 193 | int done = 0; 194 | BYTE *pBuf = (BYTE *)_pBuf; 195 | 196 | while (count) { 197 | if (!firstBuf) { 198 | firstBuf = bufQ.Dequeue(); 199 | if (!firstBuf) { 200 | lastBuf = NULL; 201 | break; 202 | } 203 | } 204 | 205 | int len = firstBuf->read(pBuf, count); 206 | 207 | if (len < 0) { 208 | delete firstBuf; 209 | firstBuf = NULL; 210 | } else { 211 | if (!len) 212 | break; 213 | pBuf += len; 214 | count -= len; 215 | done += len; 216 | } 217 | } 218 | 219 | busy -= done; 220 | 221 | return done; 222 | } 223 | 224 | void DataStream::Clean() 225 | { 226 | ChunkStream *buf; 227 | while ((buf = bufQ.Dequeue()) != NULL) 228 | delete buf; 229 | if (firstBuf) 230 | delete firstBuf; 231 | firstBuf = lastBuf = NULL; 232 | busy = 0; 233 | eof = FALSE; 234 | diag = 0; 235 | } 236 | /////////////////////////////////////////////////////////////// 237 | #if PTRACING 238 | void RenameCurrentThread(const PString &newname) 239 | { 240 | PString oldname = PThread::Current()->GetThreadName(); 241 | 242 | PThread::Current()->SetThreadName(PString(newname) 243 | #if defined(PROCESS_PER_THREAD) 244 | + ":" + PString((unsigned)getpid()) 245 | #else 246 | #if defined(P_PTHREADS) 247 | + ":" + PString((unsigned)pthread_self()) 248 | #else 249 | + ":%0x" 250 | #endif 251 | #endif 252 | ); 253 | myPTRACE(2, "T38Modem\tRenameCurrentThread old ThreadName=" << oldname); 254 | } 255 | #endif /* PTRACING */ 256 | /////////////////////////////////////////////////////////////// 257 | #ifdef PROCESS_PER_THREAD 258 | #include 259 | static double clktck = sysconf(_SC_CLK_TCK); 260 | 261 | const PString GetThreadTimes(const char *head, const char *tail) 262 | { 263 | struct tms t; 264 | 265 | if (clktck && times(&t) != -1) { 266 | return psprintf("%suser=%.3f, system=%.3f%s", 267 | head, 268 | t.tms_utime/clktck, 269 | t.tms_stime/clktck, 270 | tail); 271 | } 272 | return ""; 273 | } 274 | #endif 275 | /////////////////////////////////////////////////////////////// 276 | 277 | -------------------------------------------------------------------------------- /pmodemi.cxx: -------------------------------------------------------------------------------- 1 | /* 2 | * pmodemi.cxx 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2001-2010 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): Equivalence Pty ltd 25 | * 26 | * $Log: pmodemi.cxx,v $ 27 | * Revision 1.17 2010-10-06 16:54:19 vfrolov 28 | * Redesigned engine opening/closing 29 | * 30 | * Revision 1.17 2010/10/06 16:54:19 vfrolov 31 | * Redesigned engine opening/closing 32 | * 33 | * Revision 1.16 2010/09/29 11:52:59 vfrolov 34 | * Redesigned engine attaching/detaching 35 | * 36 | * Revision 1.15 2009/07/08 18:43:44 vfrolov 37 | * Added PseudoModem::ttyName() 38 | * 39 | * Revision 1.14 2008/09/10 11:15:00 frolov 40 | * Ported to OPAL SVN trunk 41 | * 42 | * Revision 1.13 2007/03/23 10:14:35 vfrolov 43 | * Implemented voice mode functionality 44 | * 45 | * Revision 1.12 2005/02/03 11:32:12 vfrolov 46 | * Fixed MSVC compile warnings 47 | * 48 | * Revision 1.11 2004/07/07 12:38:32 vfrolov 49 | * The code for pseudo-tty (pty) devices that communicates with fax application formed to PTY driver. 50 | * 51 | * Revision 1.10 2004/07/07 07:49:19 vfrolov 52 | * Included ptlib.h for precompiling 53 | * 54 | * Revision 1.9 2004/03/01 17:18:46 vfrolov 55 | * Increased MAX_qBUF 56 | * 57 | * Revision 1.8 2003/12/04 12:10:16 vfrolov 58 | * Tuned max delay for buffer full condition 59 | * 60 | * Revision 1.7 2002/12/30 12:49:33 vfrolov 61 | * Added tracing thread's CPU usage (Linux only) 62 | * 63 | * Revision 1.6 2002/12/20 10:12:54 vfrolov 64 | * Implemented tracing with PID of thread (for LinuxThreads) 65 | * or ID of thread (for other POSIX Threads) 66 | * 67 | * Revision 1.5 2002/05/15 16:17:55 vfrolov 68 | * Implemented per modem routing for I/C calls 69 | * 70 | * Revision 1.4 2002/03/05 12:40:27 vfrolov 71 | * Changed class hierarchy 72 | * PseudoModem is abstract 73 | * PseudoModemBody is child of PseudoModem 74 | * Added PseudoModemQ::CreateModem() to create instances 75 | * 76 | * Revision 1.3 2002/03/01 08:53:12 vfrolov 77 | * Added Copyright header 78 | * Some OS specific code moved from pmodemi.cxx to pty.cxx 79 | * Added error code string to log 80 | * Fixed race condition with fast close and open slave tty 81 | * Some other changes 82 | * 83 | * Revision 1.2 2002/01/10 06:10:03 craigs 84 | * Added MPL header 85 | * 86 | * Revision 1.1 2002/01/01 23:06:54 craigs 87 | * Initial version 88 | * 89 | */ 90 | 91 | #include 92 | #include "pmodemi.h" 93 | #include "pmodeme.h" 94 | 95 | #define new PNEW 96 | 97 | /////////////////////////////////////////////////////////////// 98 | PseudoModemBody::PseudoModemBody(const PString &_tty, const PString &_route, const PNotifier &_callbackEndPoint) 99 | : PseudoModem(_tty), 100 | route(_route), 101 | callbackEndPoint(_callbackEndPoint), 102 | engine(NULL) 103 | { 104 | } 105 | 106 | PseudoModemBody::~PseudoModemBody() 107 | { 108 | myPTRACE(1, "T38Modem\tPseudoModemBody::~PseudoModemBody()"); 109 | PseudoModemBody::StopAll(); 110 | } 111 | 112 | PBoolean PseudoModemBody::IsReady() const 113 | { 114 | PWaitAndSignal mutexWait(Mutex); 115 | return engine && engine->IsReady(); 116 | } 117 | 118 | PBoolean PseudoModemBody::CheckRoute(const PString &number) const 119 | { 120 | return route.IsEmpty() || number.Find(route) == 0; 121 | } 122 | 123 | PBoolean PseudoModemBody::Request(PStringToString &request) const 124 | { 125 | PWaitAndSignal mutexWait(Mutex); 126 | return engine && engine->Request(request); 127 | } 128 | 129 | T38Engine *PseudoModemBody::NewPtrT38Engine() const 130 | { 131 | PWaitAndSignal mutexWait(Mutex); 132 | if (engine == NULL) 133 | return NULL; 134 | 135 | return engine->NewPtrT38Engine(); 136 | } 137 | 138 | EngineBase *PseudoModemBody::NewPtrUserInputEngine() const 139 | { 140 | PWaitAndSignal mutexWait(Mutex); 141 | if (engine == NULL) 142 | return NULL; 143 | 144 | return engine->NewPtrUserInputEngine(); 145 | } 146 | 147 | void PseudoModemBody::ToPtyQ(const void *buf, PINDEX count, PBoolean OutQ) 148 | { 149 | if( count == 0 ) 150 | return; 151 | 152 | PBYTEArrayQ &PtyQ = OutQ ? outPtyQ : inPtyQ; 153 | 154 | for( int delay = 10 ;; delay *= 2 ) { 155 | static const PINDEX MAX_qBUF = 1024*2; 156 | static const int MAX_delay = ((MAX_qBUF/2)*8*1000)/14400; 157 | PINDEX busy = PtyQ.GetCount(); 158 | 159 | if( busy < MAX_qBUF ) { 160 | PINDEX free = MAX_qBUF - busy; 161 | PINDEX len = count; 162 | if( len > free ) 163 | len = free; 164 | PtyQ.Enqueue(new PBYTEArray((const BYTE *)buf, len)); 165 | buf = (const BYTE *)buf + len; 166 | count -= len; 167 | } 168 | 169 | { 170 | PWaitAndSignal mutexWait(Mutex); 171 | ModemThreadChild *notify = OutQ ? GetPtyNotifier() : (ModemThreadChild *)engine; 172 | if (notify == NULL) { 173 | myPTRACE(1, "T38Modem\tPseudoModemBody::ToPtyQ notify == NULL"); 174 | PtyQ.Clean(); 175 | return; 176 | } 177 | notify->SignalDataReady(); 178 | } 179 | if( count == 0 ) 180 | return; 181 | 182 | if (stop) 183 | break; 184 | 185 | if (delay > MAX_delay) { 186 | delay = MAX_delay; 187 | myPTRACE(2, "T38Modem\tPseudoModemBody::ToPtyQ(" << (OutQ ? "outPtyQ" : "inPtyQ") << ")" 188 | << " busy=" << busy << " count=" << count << " delay=" << delay); 189 | } 190 | PThread::Sleep(delay); 191 | if( stop ) break; 192 | } 193 | } 194 | 195 | PBoolean PseudoModemBody::StartAll() 196 | { 197 | if (engine) 198 | return TRUE; 199 | 200 | if ((engine = new ModemEngine(*this)) != NULL) { 201 | engine->Resume(); 202 | return TRUE; 203 | } 204 | PseudoModemBody::StopAll(); 205 | return FALSE; 206 | } 207 | 208 | void PseudoModemBody::StopAll() 209 | { 210 | myPTRACE(4, "T38Modem\tPseudoModemBody::StopAll() engine = " << engine); 211 | if (engine) { 212 | engine->SignalStop(); 213 | engine->WaitForTermination(); 214 | PWaitAndSignal mutexWait(Mutex); 215 | delete engine; 216 | engine = NULL; 217 | } 218 | outPtyQ.Clean(); 219 | inPtyQ.Clean(); 220 | childstop = FALSE; 221 | } 222 | 223 | PBoolean PseudoModemBody::AddModem() const 224 | { 225 | PStringToString request; 226 | request.SetAt("modemtoken", modemToken()); 227 | request.SetAt("command", "addmodem"); 228 | callbackEndPoint(request, 10); 229 | return request("response") == "confirm"; 230 | } 231 | 232 | void PseudoModemBody::Main() 233 | { 234 | RenameCurrentThread(ptyName() + "(b)"); 235 | 236 | myPTRACE(2, "T38Modem\tStarted for " << ttyPath() << 237 | " (accepts " << (route.IsEmpty() ? PString("all") : route) << ")"); 238 | 239 | MainLoop(); 240 | 241 | myPTRACE(2, "T38Modem\tStopped " << GetThreadTimes(", CPU usage: ")); 242 | } 243 | /////////////////////////////////////////////////////////////// 244 | 245 | -------------------------------------------------------------------------------- /enginebase.h: -------------------------------------------------------------------------------- 1 | /* 2 | * enginebase.h 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2007-2010 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): 25 | * 26 | * $Log: enginebase.h,v $ 27 | * Revision 1.14 2010-10-12 16:46:25 vfrolov 28 | * Implemented fake streams 29 | * 30 | * Revision 1.14 2010/10/12 16:46:25 vfrolov 31 | * Implemented fake streams 32 | * 33 | * Revision 1.13 2010/10/08 06:04:59 vfrolov 34 | * Added diagErrorMask 35 | * 36 | * Revision 1.12 2010/10/06 16:54:19 vfrolov 37 | * Redesigned engine opening/closing 38 | * 39 | * Revision 1.11 2010/09/29 11:52:59 vfrolov 40 | * Redesigned engine attaching/detaching 41 | * 42 | * Revision 1.10 2010/09/22 15:07:45 vfrolov 43 | * Added ResetModemState() and OnResetModemState() 44 | * 45 | * Revision 1.9 2010/09/08 17:22:23 vfrolov 46 | * Redesigned modem engine (continue) 47 | * 48 | * Revision 1.8 2010/07/07 08:09:47 vfrolov 49 | * Added IsAttached() 50 | * 51 | * Revision 1.7 2010/03/18 08:42:17 vfrolov 52 | * Added named tracing of data types 53 | * 54 | * Revision 1.6 2009/11/19 14:48:28 vfrolov 55 | * Moved common code to class EngineBase 56 | * 57 | * Revision 1.5 2009/11/19 11:14:04 vfrolov 58 | * Added OnUserInput 59 | * 60 | * Revision 1.4 2009/11/18 19:08:47 vfrolov 61 | * Moved common code to class EngineBase 62 | * 63 | * Revision 1.3 2008/09/10 11:15:00 frolov 64 | * Ported to OPAL SVN trunk 65 | * 66 | * Revision 1.2 2007/04/09 08:07:12 vfrolov 67 | * Added symbolic logging ModemCallbackParam 68 | * 69 | * Revision 1.1 2007/03/23 09:54:45 vfrolov 70 | * Initial revision 71 | * 72 | */ 73 | 74 | #ifndef _ENGINEBASE_H 75 | #define _ENGINEBASE_H 76 | 77 | /////////////////////////////////////////////////////////////// 78 | class DataStream; 79 | /////////////////////////////////////////////////////////////// 80 | class ReferenceObject : public PObject 81 | { 82 | PCLASSINFO(ReferenceObject, PObject); 83 | 84 | public: 85 | ReferenceObject() : referenceCount(1) {} 86 | 87 | void AddReference() { 88 | PWaitAndSignal mutex(referenceCountMutex); 89 | ++referenceCount; 90 | } 91 | 92 | static void DelPointer(ReferenceObject * object) { 93 | PBoolean doDelele; 94 | 95 | object->referenceCountMutex.Wait(); 96 | doDelele = (--object->referenceCount == 0); 97 | object->referenceCountMutex.Signal(); 98 | 99 | if (doDelele) 100 | delete object; 101 | } 102 | 103 | private: 104 | PMutex referenceCountMutex; 105 | unsigned referenceCount; 106 | }; 107 | /////////////////////////////////////////////////////////////// 108 | class EngineBase : public ReferenceObject 109 | { 110 | PCLASSINFO(EngineBase, ReferenceObject); 111 | 112 | private: 113 | class OWNERIN { int unused; }; 114 | class OWNEROUT { int unused; }; 115 | 116 | public: 117 | typedef const OWNERIN *HOWNERIN; 118 | typedef const OWNEROUT *HOWNEROUT; 119 | 120 | public: 121 | 122 | /**@name Construction */ 123 | //@{ 124 | EngineBase(const PString &_name = ""); 125 | virtual ~EngineBase(); 126 | //@} 127 | 128 | enum { 129 | diagNoCarrier = 0x0001, 130 | diagOutOfOrder = 0x0100, 131 | diagDiffSig = 0x0400, // a different signal is detected 132 | diagBadFcs = 0x0800, 133 | diagError = 0x8000, // bad usage 134 | 135 | diagErrorMask = 0xFF00, 136 | }; 137 | 138 | enum DataType { 139 | dtNone, 140 | dtRing, 141 | dtBusy, 142 | dtCed, 143 | dtCng, 144 | dtSilence, 145 | dtHdlc, 146 | dtRaw, 147 | }; 148 | 149 | enum ModemCallbackParam { 150 | cbpUserDataMask = 0xFF, 151 | cbpOutBufNoFull = 256, 152 | cbpUpdateState = 257, 153 | cbpReset = -1, 154 | cbpOutBufEmpty = -2, 155 | cbpUserInput = -3, 156 | }; 157 | 158 | enum ModemClass { 159 | mcUndefined, 160 | mcFax, 161 | }; 162 | 163 | /**@name Modem API */ 164 | //@{ 165 | const PString &Name() const { return name; } 166 | 167 | PBoolean Attach(const PNotifier &callback); 168 | void Detach(const PNotifier &callback); 169 | void ResetModemState(); 170 | 171 | void OpenIn(HOWNERIN hOwner, PBoolean fake = FALSE); 172 | void OpenOut(HOWNEROUT hOwner, PBoolean fake = FALSE); 173 | void CloseIn(HOWNERIN hOwner); 174 | void CloseOut(HOWNEROUT hOwner); 175 | void EnableFakeIn(PBoolean enable = TRUE); 176 | void EnableFakeOut(PBoolean enable = TRUE); 177 | 178 | PBoolean IsOpenIn() const { return hOwnerIn != NULL; } 179 | PBoolean IsOpenOut() const { return hOwnerOut != NULL; } 180 | 181 | PBoolean TryLockModemCallback(); 182 | void UnlockModemCallback(); 183 | 184 | void ChangeModemClass(ModemClass newModemClass); 185 | 186 | void WriteUserInput(const PString & value); 187 | int RecvUserInput(void * pBuf, PINDEX count); 188 | 189 | virtual void SendOnIdle(DataType /*_dataType*/) {} 190 | virtual PBoolean SendStart(DataType _dataType, int param) = 0; 191 | virtual int Send(const void *pBuf, PINDEX count) = 0; 192 | virtual PBoolean SendStop(PBoolean moreFrames, int _callbackParam) = 0; 193 | virtual PBoolean isOutBufFull() const = 0; 194 | virtual PBoolean SendingNotCompleted() const { return FALSE; } 195 | 196 | virtual void RecvOnIdle(DataType /*_dataType*/) {} 197 | virtual PBoolean RecvWait(DataType _dataType, int param, int _callbackParam, PBoolean &done) = 0; 198 | virtual PBoolean RecvStart(int _callbackParam) = 0; 199 | virtual int Recv(void *pBuf, PINDEX count) = 0; 200 | virtual void RecvStop() = 0; 201 | virtual int RecvDiag() const { return 0; }; 202 | //@} 203 | 204 | protected: 205 | PBoolean IsModemOpen() const { return !modemCallback.IsNULL(); } 206 | 207 | virtual void OnAttach(); 208 | virtual void OnDetach(); 209 | virtual void OnResetModemState(); 210 | virtual void OnChangeModemClass(); 211 | virtual void OnUserInput(const PString & value); 212 | 213 | virtual void OnOpenIn(); 214 | virtual void OnOpenOut(); 215 | virtual void OnCloseIn(); 216 | virtual void OnCloseOut(); 217 | virtual void OnChangeEnableFakeIn(); 218 | virtual void OnChangeEnableFakeOut(); 219 | 220 | const PString name; 221 | DataStream *volatile recvUserInput; 222 | ModemClass modemClass; 223 | volatile HOWNERIN hOwnerIn; 224 | volatile HOWNEROUT hOwnerOut; 225 | PBoolean firstIn; 226 | PBoolean firstOut; 227 | PBoolean isFakeOwnerIn; 228 | PBoolean isFakeOwnerOut; 229 | PBoolean isEnableFakeIn; 230 | PBoolean isEnableFakeOut; 231 | 232 | void ModemCallbackWithUnlock(INT extra); 233 | 234 | PNotifier modemCallback; 235 | PTimedMutex MutexModemCallback; 236 | 237 | PMutex MutexModem; 238 | PMutex MutexIn; 239 | PMutex MutexOut; 240 | PMutex Mutex; 241 | }; 242 | 243 | #if PTRACING 244 | ostream & operator<<(ostream & out, EngineBase::DataType dataType); 245 | ostream & operator<<(ostream & out, EngineBase::ModemCallbackParam param); 246 | ostream & operator<<(ostream & out, EngineBase::ModemClass modemClass); 247 | #endif 248 | /////////////////////////////////////////////////////////////// 249 | 250 | #endif // _ENGINEBASE_H 251 | 252 | -------------------------------------------------------------------------------- /t30tone.cxx: -------------------------------------------------------------------------------- 1 | /* 2 | * t30tone.cxx 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2002-2010 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): Equivalence Pty ltd 25 | * 26 | * $Log: t30tone.cxx,v $ 27 | * Revision 1.8 2010-10-12 16:46:25 vfrolov 28 | * Implemented fake streams 29 | * 30 | * Revision 1.8 2010/10/12 16:46:25 vfrolov 31 | * Implemented fake streams 32 | * 33 | * Revision 1.7 2010/09/10 18:00:44 vfrolov 34 | * Cleaned up code 35 | * 36 | * Revision 1.6 2008/09/10 11:15:00 frolov 37 | * Ported to OPAL SVN trunk 38 | * 39 | * Revision 1.5 2007/03/23 10:14:36 vfrolov 40 | * Implemented voice mode functionality 41 | * 42 | * Revision 1.4 2005/02/03 11:32:12 vfrolov 43 | * Fixed MSVC compile warnings 44 | * 45 | * Revision 1.3 2004/07/06 16:07:24 vfrolov 46 | * Included ptlib.h for precompiling 47 | * 48 | * Revision 1.2 2002/06/07 06:25:15 robertj 49 | * Added math.h for use of sin() function. 50 | * Fixed GNU warnings. 51 | * 52 | * Revision 1.1 2002/04/30 10:59:07 vfrolov 53 | * Initial revision 54 | * 55 | */ 56 | 57 | #include 58 | #include "pmutils.h" 59 | #include "t30tone.h" 60 | 61 | /////////////////////////////////////////////////////////////// 62 | 63 | #define new PNEW 64 | 65 | /////////////////////////////////////////////////////////////// 66 | typedef PInt16 SIMPLE_TYPE; 67 | #define BYTES_PER_SIMPLE sizeof(SIMPLE_TYPE) 68 | #define SIMPLES_PER_SEC 8000 69 | /////////////////////////////////////////////////////////////// 70 | #define CNG_HZ 1100 71 | #define CNG_ON_MSEC 500 72 | #define CNG_OFF_MSEC 3000 73 | /////////////////////////////////////////////////////////////// 74 | #define CNG_FILTER_BUF_LEN ((((SIMPLES_PER_SEC + CNG_HZ - 1)/CNG_HZ + 1)/2)*2) 75 | 76 | #define tone_trace(cng_filter_buf, power, cng_power, cng_power_norm) 77 | #ifndef tone_trace 78 | static void tone_trace(const long *cng_filter_buf, long power, long cng_power, long cng_power_norm) 79 | { 80 | PString str; 81 | 82 | for (PINDEX i = 0 ; i < CNG_FILTER_BUF_LEN ; i++) { 83 | str += PString(cng_filter_buf[i]); 84 | str += " "; 85 | } 86 | 87 | myPTRACE(1, "T38Modem\t" << str << " pw=" << power << " cng_pw=" << cng_power << " norm=" << cng_power_norm); 88 | } 89 | #endif 90 | 91 | enum { 92 | cng_phase_off_head, 93 | cng_phase_on, 94 | cng_phase_off_tail, 95 | }; 96 | 97 | T30ToneDetect::T30ToneDetect() 98 | { 99 | cng_filter_buf = new long[CNG_FILTER_BUF_LEN]; 100 | memset(cng_filter_buf, 0, CNG_FILTER_BUF_LEN*sizeof(cng_filter_buf[0])); 101 | 102 | index = 0; 103 | power = 0; 104 | 105 | cng_on_count = 0; 106 | cng_off_count = 0; 107 | cng_phase = cng_phase_off_head; 108 | } 109 | 110 | T30ToneDetect::~T30ToneDetect() 111 | { 112 | delete [] cng_filter_buf; 113 | } 114 | 115 | #define CNG_FILTER_CHUNK_LEN 20 116 | #define CNG_ON_CHUNKS_MIN (((CNG_HZ*CNG_ON_MSEC)*60)/((CNG_FILTER_CHUNK_LEN*1000)*100)) 117 | #define CNG_ON_CHUNKS_MAX (((CNG_HZ*CNG_ON_MSEC)*140)/((CNG_FILTER_CHUNK_LEN*1000)*100)) 118 | #define CNG_OFF_CHUNKS_MIN (((CNG_HZ*CNG_OFF_MSEC)*30)/((CNG_FILTER_CHUNK_LEN*1000)*100)) 119 | 120 | PBoolean T30ToneDetect::Write(const void * buffer, PINDEX len) 121 | { 122 | PBoolean detected = FALSE; 123 | 124 | SIMPLE_TYPE *pBuf = (SIMPLE_TYPE *)buffer; 125 | len /= BYTES_PER_SIMPLE; 126 | 127 | while (len) { 128 | PINDEX iBuf = 0; 129 | 130 | // filter CNG and calculate total power 131 | 132 | PINDEX index0 = index; 133 | 134 | while (index < CNG_FILTER_BUF_LEN*CNG_FILTER_CHUNK_LEN) { 135 | iBuf = ((index - index0)*SIMPLES_PER_SEC)/(CNG_FILTER_BUF_LEN*CNG_HZ); 136 | 137 | if (iBuf >= len) 138 | return detected; 139 | 140 | SIMPLE_TYPE pw = pBuf[iBuf]; 141 | 142 | cng_filter_buf[index%CNG_FILTER_BUF_LEN] += pw; 143 | 144 | if (pw < 0) 145 | power -= pw; 146 | else 147 | power += pw; 148 | 149 | index++; 150 | } 151 | 152 | // calculate CNG power 153 | 154 | PINDEX i; 155 | long cng_power_cur = 0; 156 | 157 | for (i = 0 ; i < CNG_FILTER_BUF_LEN/2 ; i++) 158 | cng_power_cur += cng_filter_buf[i]; 159 | 160 | for (; i < CNG_FILTER_BUF_LEN ; i++) 161 | cng_power_cur -= cng_filter_buf[i]; 162 | 163 | long cng_power; 164 | 165 | if (cng_power_cur < 0) 166 | cng_power = -cng_power_cur; 167 | else 168 | cng_power = cng_power_cur; 169 | 170 | for (i = 1 ; i < CNG_FILTER_BUF_LEN/2 ; i++) { 171 | cng_power_cur -= cng_filter_buf[i]*2; 172 | cng_power_cur += cng_filter_buf[i + CNG_FILTER_BUF_LEN/2]*2; 173 | 174 | if (cng_power_cur < 0) { 175 | if (cng_power < -cng_power_cur) 176 | cng_power = -cng_power_cur; 177 | } else { 178 | if (cng_power < cng_power_cur) 179 | cng_power = cng_power_cur; 180 | } 181 | } 182 | 183 | long cng_power_norm = cng_power * 1000; 184 | 185 | if (power > 1) 186 | cng_power_norm /= power; 187 | 188 | if (cng_on_count > 1) 189 | cng_power_norm = (cng_power_norm*140)/100; 190 | if (cng_off_count > 1) 191 | cng_power_norm = (cng_power_norm*80)/100; 192 | 193 | if (cng_power_norm > 500) { 194 | cng_on_count++; 195 | 196 | switch (cng_phase) { 197 | case cng_phase_off_head: 198 | if (cng_off_count >= CNG_OFF_CHUNKS_MIN) 199 | cng_phase = cng_phase_on; 200 | else 201 | cng_phase = cng_phase_off_head; 202 | break; 203 | 204 | case cng_phase_on: 205 | break; 206 | 207 | case cng_phase_off_tail: 208 | cng_phase = cng_phase_off_head; 209 | break; 210 | 211 | default: 212 | cng_phase = cng_phase_off_head; 213 | } 214 | 215 | if (cng_off_count) { 216 | myPTRACE(2, "T38Modem\tcng_off_count=" << cng_off_count); 217 | cng_off_count = 0; 218 | } 219 | 220 | tone_trace(cng_filter_buf, power, cng_power, cng_power_norm); 221 | } else { 222 | cng_off_count++; 223 | 224 | switch (cng_phase) { 225 | case cng_phase_off_head: 226 | break; 227 | 228 | case cng_phase_on: 229 | if (cng_on_count >= CNG_ON_CHUNKS_MIN && cng_on_count <= CNG_ON_CHUNKS_MAX) 230 | cng_phase = cng_phase_off_tail; 231 | else 232 | cng_phase = cng_phase_off_head; 233 | break; 234 | 235 | case cng_phase_off_tail: 236 | if (cng_off_count >= CNG_OFF_CHUNKS_MIN) { 237 | myPTRACE(1, "T38Modem\tDetected CNG"); 238 | cng_phase = cng_phase_off_head; 239 | detected = TRUE; 240 | } 241 | break; 242 | 243 | default: 244 | cng_phase = cng_phase_off_head; 245 | } 246 | 247 | if (cng_on_count) { 248 | myPTRACE(2, "T38Modem\tcng_on_count=" << cng_on_count); 249 | tone_trace(cng_filter_buf, power, cng_power, cng_power_norm); 250 | 251 | cng_on_count = 0; 252 | } 253 | } 254 | 255 | // reatart filter 256 | 257 | memset(cng_filter_buf, 0, CNG_FILTER_BUF_LEN*sizeof(cng_filter_buf[0])); 258 | index = 0; 259 | power = 0; 260 | 261 | // next chunk 262 | 263 | iBuf++; 264 | pBuf += iBuf; 265 | len -= iBuf; 266 | } 267 | 268 | return detected; 269 | } 270 | /////////////////////////////////////////////////////////////// 271 | 272 | -------------------------------------------------------------------------------- /pmutils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * pmutils.h 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2001-2008 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): Equivalence Pty ltd 25 | * 26 | * $Log: pmutils.h,v $ 27 | * Revision 1.18 2008-09-10 11:15:00 frolov 28 | * Ported to OPAL SVN trunk 29 | * 30 | * Revision 1.18 2008/09/10 11:15:00 frolov 31 | * Ported to OPAL SVN trunk 32 | * 33 | * Revision 1.17 2006/12/11 10:27:35 vfrolov 34 | * Disabled renaming thread if no PTRACING 35 | * 36 | * Revision 1.16 2005/03/05 15:39:12 vfrolov 37 | * Ignore COUT_TRACE if not PTRACING 38 | * 39 | * Revision 1.15 2005/02/04 10:18:49 vfrolov 40 | * Fixed warnings for No Trace build 41 | * 42 | * Revision 1.14 2005/02/03 11:32:12 vfrolov 43 | * Fixed MSVC compile warnings 44 | * 45 | * Revision 1.13 2004/10/20 14:15:09 vfrolov 46 | * Added reset of signal counter to WaitDataReady() 47 | * 48 | * Revision 1.12 2004/07/07 07:53:58 vfrolov 49 | * Moved ptlib.h including to *.cxx for precompiling 50 | * Fixed compiler warning 51 | * 52 | * Revision 1.11 2004/03/09 17:23:19 vfrolov 53 | * Added PROCESS_PER_THREAD ifdef 54 | * 55 | * Revision 1.10 2003/12/04 13:22:35 vfrolov 56 | * Removed ambiguous isEof() 57 | * Improved memory usage in DataStream 58 | * Fixed myPTRACE 59 | * 60 | * Revision 1.9 2003/01/08 16:37:29 vfrolov 61 | * Changed class DataStream: 62 | * members moved to private section and added isEof() 63 | * added threshold and isFull() 64 | * 65 | * Revision 1.8 2002/12/30 12:49:39 vfrolov 66 | * Added tracing thread's CPU usage (Linux only) 67 | * 68 | * Revision 1.7 2002/12/20 10:13:01 vfrolov 69 | * Implemented tracing with PID of thread (for LinuxThreads) 70 | * or ID of thread (for other POSIX Threads) 71 | * 72 | * Revision 1.6 2002/04/27 10:12:21 vfrolov 73 | * If defined MYPTRACE_LEVEL=N then myPTRACE() will output the trace with level N 74 | * 75 | * Revision 1.5 2002/03/07 07:30:44 vfrolov 76 | * Fixed endless recursive call SignalChildStop(). Possible there is 77 | * a bug in gcc version 2.95.4 20010902 (Debian prerelease). 78 | * Markus Storm reported the promlem. 79 | * 80 | * Revision 1.4 2002/03/01 08:17:28 vfrolov 81 | * Added Copyright header 82 | * Removed virtual modifiers 83 | * 84 | * Revision 1.3 2002/02/11 08:35:12 vfrolov 85 | * myPTRACE() outputs trace to cout only if defined COUT_TRACE 86 | * 87 | * Revision 1.2 2002/01/10 06:10:03 craigs 88 | * Added MPL header 89 | * 90 | * Revision 1.1 2002/01/01 23:06:54 craigs 91 | * Initial version 92 | * 93 | */ 94 | 95 | #ifndef _PMUTILS_H 96 | #define _PMUTILS_H 97 | 98 | /////////////////////////////////////////////////////////////// 99 | class ModemThread : public PThread 100 | { 101 | PCLASSINFO(ModemThread, PThread); 102 | public: 103 | /**@name Construction */ 104 | //@{ 105 | ModemThread(); 106 | //@} 107 | 108 | /**@name Operations */ 109 | //@{ 110 | void SignalDataReady() { dataReadySyncPoint.Signal(); } 111 | void SignalChildStop(); 112 | virtual void SignalStop(); 113 | //@} 114 | 115 | protected: 116 | virtual void Main() = 0; 117 | void WaitDataReady(); 118 | 119 | volatile PBoolean stop; // *this was requested to stop 120 | volatile PBoolean childstop; // there is a child that was requested to stop 121 | PSyncPoint dataReadySyncPoint; 122 | }; 123 | /////////////////////////////////////////////////////////////// 124 | class ModemThreadChild : public ModemThread 125 | { 126 | PCLASSINFO(ModemThreadChild, ModemThread); 127 | public: 128 | /**@name Construction */ 129 | //@{ 130 | ModemThreadChild(ModemThread &_parent); 131 | //@} 132 | 133 | /**@name Operations */ 134 | //@{ 135 | virtual void SignalStop(); 136 | //@} 137 | 138 | protected: 139 | ModemThread &parent; 140 | }; 141 | /////////////////////////////////////////////////////////////// 142 | PQUEUE(_PBYTEArrayQ, PBYTEArray); 143 | 144 | class PBYTEArrayQ : public _PBYTEArrayQ 145 | { 146 | PCLASSINFO(PBYTEArrayQ, _PBYTEArrayQ); 147 | public: 148 | PBYTEArrayQ() : count(0) {} 149 | ~PBYTEArrayQ() { Clean(); } 150 | 151 | virtual void Enqueue(PBYTEArray *buf) { 152 | PWaitAndSignal mutexWait(Mutex); 153 | count += buf->GetSize(); 154 | _PBYTEArrayQ::Enqueue(buf); 155 | } 156 | 157 | virtual PBYTEArray *Dequeue() { 158 | PWaitAndSignal mutexWait(Mutex); 159 | PBYTEArray *buf = _PBYTEArrayQ::Dequeue(); 160 | if( buf ) count -= buf->GetSize(); 161 | return buf; 162 | } 163 | 164 | PINDEX GetCount() const { return count; } 165 | 166 | void Clean() { 167 | PBYTEArray *buf; 168 | while( (buf = Dequeue()) != NULL ) { 169 | delete buf; 170 | } 171 | } 172 | protected: 173 | PINDEX count; 174 | PMutex Mutex; 175 | }; 176 | /////////////////////////////////////////////////////////////// 177 | class ChunkStream : public PObject 178 | { 179 | PCLASSINFO(ChunkStream, PObject); 180 | public: 181 | ChunkStream() : first(0), last(0) {} 182 | 183 | int write(const void *pBuf, PINDEX count); 184 | int read(void *pBuf, PINDEX count); 185 | 186 | private: 187 | BYTE data[256]; 188 | PINDEX first; 189 | PINDEX last; 190 | }; 191 | 192 | PQUEUE(ChunkStreamQ, ChunkStream); 193 | /////////////////////////////////////////////////////////////// 194 | class DataStream : public PObject 195 | { 196 | PCLASSINFO(DataStream, PObject); 197 | public: 198 | DataStream(PINDEX _threshold = 0) 199 | : firstBuf(NULL), lastBuf(NULL), busy(0), 200 | threshold(_threshold), eof(FALSE), diag(0) {} 201 | ~DataStream() { DataStream::Clean(); } 202 | 203 | int PutData(const void *pBuf, PINDEX count); 204 | int GetData(void *pBuf, PINDEX count); 205 | void PutEof() { eof = TRUE; } 206 | int GetDiag() const { return diag; } 207 | DataStream &SetDiag(int _diag) { diag = _diag; return *this; } 208 | PBoolean isFull() const { return threshold && threshold < busy; } 209 | virtual void Clean(); 210 | 211 | private: 212 | ChunkStream *firstBuf; 213 | ChunkStreamQ bufQ; 214 | ChunkStream *lastBuf; // if not NULL then it should be in bufQ or firstBuf 215 | PINDEX busy; 216 | 217 | PINDEX threshold; 218 | PBoolean eof; 219 | int diag; 220 | }; 221 | /////////////////////////////////////////////////////////////// 222 | PQUEUE(_DataStreamQ, DataStream); 223 | 224 | class DataStreamQ : public _DataStreamQ 225 | { 226 | PCLASSINFO(DataStreamQ, _DataStreamQ); 227 | public: 228 | DataStreamQ() {} 229 | ~DataStreamQ() { Clean(); } 230 | 231 | virtual void Enqueue(DataStream *buf) { 232 | PWaitAndSignal mutexWait(Mutex); 233 | _DataStreamQ::Enqueue(buf); 234 | } 235 | 236 | virtual DataStream *Dequeue() { 237 | PWaitAndSignal mutexWait(Mutex); 238 | return _DataStreamQ::Dequeue(); 239 | } 240 | 241 | void Clean() { 242 | DataStream *buf; 243 | while( (buf = Dequeue()) != NULL ) { 244 | delete buf; 245 | } 246 | } 247 | protected: 248 | PMutex Mutex; 249 | }; 250 | /////////////////////////////////////////////////////////////// 251 | #ifdef _MSC_VER 252 | // warning C4127: conditional expression is constant 253 | #pragma warning(disable:4127) 254 | #endif // _MSC_VER 255 | 256 | #if !PTRACING && defined COUT_TRACE 257 | #undef COUT_TRACE 258 | #endif 259 | 260 | #ifdef COUT_TRACE 261 | #define _myPTRACE(level, args) do { \ 262 | PTRACE(level, args); \ 263 | cout << PThread::Current()->GetThreadName() << ": " << args << endl; \ 264 | } while(0) 265 | #define myCanTrace(level) TRUE 266 | #define myPTRACE_PARAM(param) param 267 | #else 268 | #define _myPTRACE(level, args) do { PTRACE(level, args); } while(0) 269 | #define myCanTrace(level) PTrace::CanTrace(level) 270 | #define myPTRACE_PARAM(param) PTRACE_PARAM(param) 271 | #endif // COUT_TRACE 272 | 273 | #ifdef MYPTRACE_LEVEL 274 | #define myPTRACE(level, args) _myPTRACE(MYPTRACE_LEVEL, args) 275 | #else 276 | #define myPTRACE(level, args) _myPTRACE(level, args) 277 | #endif // MYPTRACE_LEVEL 278 | 279 | #define PRTHEX(data) " {\n" << setprecision(2) << hex << setfill('0') << data << dec << setfill(' ') << " }" 280 | /////////////////////////////////////////////////////////////// 281 | #if PTRACING 282 | extern void RenameCurrentThread(const PString &newname); 283 | #else 284 | #define RenameCurrentThread(newname) 285 | #endif /* PTRACING */ 286 | 287 | #ifdef PROCESS_PER_THREAD 288 | extern const PString GetThreadTimes(const char *head = "", const char *tail = ""); 289 | #else 290 | inline const PString GetThreadTimes(const char *head = "", const char *tail = ""); 291 | 292 | inline const PString GetThreadTimes(const char *, const char *) 293 | { 294 | return ""; 295 | } 296 | #endif 297 | /////////////////////////////////////////////////////////////// 298 | 299 | #endif // _PMUTILS_H 300 | 301 | -------------------------------------------------------------------------------- /opal/modemstrm.cxx: -------------------------------------------------------------------------------- 1 | /* 2 | * modemstrm.cxx 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2007-2010 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): 25 | * 26 | * $Log: modemstrm.cxx,v $ 27 | * Revision 1.12 2010-10-06 16:54:19 vfrolov 28 | * Redesigned engine opening/closing 29 | * 30 | * Revision 1.12 2010/10/06 16:54:19 vfrolov 31 | * Redesigned engine opening/closing 32 | * 33 | * Revision 1.11 2010/03/15 13:46:46 vfrolov 34 | * Added resetting prepare packet timeout on start media patch for fax sink 35 | * 36 | * Revision 1.10 2010/01/14 18:32:51 vfrolov 37 | * Added ignoring packets with mismatched payload type and fake packets 38 | * 39 | * Revision 1.9 2009/12/08 15:06:22 vfrolov 40 | * Fixed incompatibility with OPAL trunk 41 | * 42 | * Revision 1.8 2009/11/26 07:24:22 vfrolov 43 | * Added adjusting sequence numbers 44 | * 45 | * Revision 1.7 2009/11/20 16:37:27 vfrolov 46 | * Fixed audio class application blocking by forced T.38 mode 47 | * 48 | * Revision 1.6 2009/11/10 08:13:38 vfrolov 49 | * Fixed race condition on re-opening T38Engine 50 | * 51 | * Revision 1.5 2009/10/27 19:03:50 vfrolov 52 | * Added ability to re-open T38Engine 53 | * Added ability to prepare IFP packets with adaptive delay/period 54 | * 55 | * Revision 1.4 2009/07/31 17:34:40 vfrolov 56 | * Removed --h323-old-asn and --sip-old-asn options 57 | * 58 | * Revision 1.3 2009/07/27 16:21:24 vfrolov 59 | * Moved h323lib specific code to h323lib directory 60 | * 61 | * Revision 1.2 2008/09/10 11:15:00 frolov 62 | * Ported to OPAL SVN trunk 63 | * 64 | * Revision 1.1 2007/05/28 12:47:52 vfrolov 65 | * Initial revision 66 | * 67 | */ 68 | 69 | #include 70 | 71 | #include 72 | 73 | #include 74 | #include 75 | 76 | #include "../t38engine.h" 77 | #include "modemstrm.h" 78 | 79 | #define new PNEW 80 | 81 | ///////////////////////////////////////////////////////////////////////////// 82 | T38ModemMediaStream::T38ModemMediaStream( 83 | OpalConnection & conn, 84 | unsigned sessionID, 85 | PBoolean isSource, 86 | T38Engine *engine) 87 | : OpalMediaStream(conn, OpalT38, sessionID, isSource) 88 | , t38engine(engine) 89 | { 90 | myPTRACE(2, "T38Modem\tT38ModemMediaStream::T38ModemMediaStream " << *this); 91 | 92 | PAssert(t38engine != NULL, "t38engine is NULL"); 93 | } 94 | 95 | T38ModemMediaStream::~T38ModemMediaStream() 96 | { 97 | ReferenceObject::DelPointer(t38engine); 98 | } 99 | 100 | PBoolean T38ModemMediaStream::Open() 101 | { 102 | if (m_isOpen) 103 | return TRUE; 104 | 105 | myPTRACE(2, "T38Modem\tT38ModemMediaStream::Open " << *this); 106 | 107 | #if 0 108 | currentSequenceNumber = 32768; 109 | #else 110 | currentSequenceNumber = 0; 111 | #endif 112 | #if PTRACING 113 | totallost = 0; 114 | #endif 115 | 116 | if (IsSink()) 117 | t38engine->OpenIn(EngineBase::HOWNERIN(this)); 118 | else 119 | t38engine->OpenOut(EngineBase::HOWNEROUT(this)); 120 | 121 | return OpalMediaStream::Open(); 122 | } 123 | 124 | void T38ModemMediaStream::InternalClose() 125 | { 126 | myPTRACE(2, "T38Modem\tT38ModemMediaStream::Close " << *this); 127 | 128 | if (IsSink()) { 129 | myPTRACE(2, "T38Modem\tT38ModemMediaStream::Close Send statistics:" 130 | " sequence=" << currentSequenceNumber << 131 | " lost=" << totallost); 132 | 133 | t38engine->CloseIn(EngineBase::HOWNERIN(this)); 134 | } else { 135 | myPTRACE(2, "T38Modem\tT38ModemMediaStream::Close Receive statistics:" 136 | " sequence=" << currentSequenceNumber); 137 | 138 | t38engine->CloseOut(EngineBase::HOWNEROUT(this)); 139 | } 140 | } 141 | 142 | void T38ModemMediaStream::OnStartMediaPatch() 143 | { 144 | if (m_isSource) { 145 | if (m_mediaPatch != NULL) { 146 | OpalMediaStreamPtr sink = m_mediaPatch->GetSink(); 147 | if (sink != NULL) { 148 | OpalMediaFormat format = sink->GetMediaFormat(); 149 | 150 | if (format.IsValid()) { 151 | if (format.GetMediaType() != OpalMediaType::Fax()) { 152 | myPTRACE(3, "T38Modem\tT38ModemMediaStream::OnStartMediaPatch: use timeout=0, period=20 for sink " << *sink); 153 | 154 | t38engine->SetPreparePacketTimeout(EngineBase::HOWNEROUT(this), 0, 20); 155 | } else { 156 | myPTRACE(3, "T38Modem\tT38ModemMediaStream::OnStartMediaPatch: use timeout=-1 for sink " << *sink); 157 | 158 | t38engine->SetPreparePacketTimeout(EngineBase::HOWNEROUT(this), -1); 159 | } 160 | } else { 161 | myPTRACE(1, "T38Modem\tT38ModemMediaStream::OnStartMediaPatch: format is invalid !!!"); 162 | } 163 | } else { 164 | myPTRACE(1, "T38Modem\tT38ModemMediaStream::OnStartMediaPatch: sink is NULL !!!"); 165 | } 166 | } else { 167 | myPTRACE(1, "T38Modem\tT38ModemMediaStream::OnStartMediaPatch: mediaPatch is NULL !!!"); 168 | } 169 | } 170 | } 171 | 172 | PBoolean T38ModemMediaStream::ReadPacket(RTP_DataFrame & packet) 173 | { 174 | if (!m_isOpen) 175 | return FALSE; 176 | 177 | T38_IFP ifp; 178 | int res; 179 | 180 | packet.SetTimestamp(m_timestamp); 181 | m_timestamp += 160; 182 | 183 | do { 184 | //myPTRACE(4, "T38Modem\tT38ModemMediaStream::ReadPacket ..."); 185 | res = t38engine->PreparePacket(EngineBase::HOWNEROUT(this), ifp); 186 | } while (currentSequenceNumber == 0 && res < 0); 187 | 188 | packet[0] = 0x80; 189 | packet.SetPayloadType(m_mediaFormat.GetPayloadType()); 190 | 191 | if (res > 0) { 192 | myPTRACE(4, "T38Modem\tT38ModemMediaStream::ReadPacket ifp = " << setprecision(2) << ifp); 193 | 194 | PASN_OctetString ifp_packet; 195 | ifp_packet.EncodeSubType(ifp); 196 | 197 | packet.SetPayloadSize(ifp_packet.GetDataLength()); 198 | memcpy(packet.GetPayloadPtr(), ifp_packet.GetPointer(), ifp_packet.GetDataLength()); 199 | packet.SetSequenceNumber(WORD(currentSequenceNumber++ & 0xFFFF)); 200 | } 201 | else 202 | if (res < 0) { 203 | // send a "repeated" packet with a "fake" payload of one byte of 0xFF 204 | 205 | //packet.SetPayloadSize(1); 206 | //packet.GetPayloadPtr()[0] = 0xFF; 207 | 208 | packet.SetPayloadSize(0); 209 | packet.SetSequenceNumber(WORD((currentSequenceNumber - 1) & 0xFFFF)); 210 | } 211 | else { 212 | return FALSE; 213 | } 214 | 215 | myPTRACE(5, "T38Modem\tT38ModemMediaStream::ReadPacket" 216 | " packet " << packet.GetSequenceNumber() << 217 | " size=" << packet.GetPayloadSize() << 218 | " type=" << packet.GetPayloadType() << 219 | " ts=" << packet.GetTimestamp()); 220 | 221 | return TRUE; 222 | } 223 | 224 | PBoolean T38ModemMediaStream::WritePacket(RTP_DataFrame & packet) 225 | { 226 | if (!m_isOpen) 227 | return FALSE; 228 | 229 | myPTRACE(5, "T38Modem\tT38ModemMediaStream::WritePacket " 230 | " packet " << packet.GetSequenceNumber() << 231 | " size=" << packet.GetPayloadSize() << 232 | " " << packet.GetPayloadType() << 233 | " " << m_mediaFormat.GetPayloadType()); 234 | 235 | #if 0 236 | if (m_mediaFormat.GetPayloadType() != packet.GetPayloadType()) { 237 | myPTRACE(5, "T38Modem\tT38ModemMediaStream::WritePacket: ignored packet with mismatched payload type"); 238 | return TRUE; 239 | } 240 | #endif 241 | 242 | long packedSequenceNumber = (packet.GetSequenceNumber() & 0xFFFF) + (currentSequenceNumber & ~0xFFFFL); 243 | long lost = packedSequenceNumber - currentSequenceNumber; 244 | 245 | if (lost < -0x10000L/2) { 246 | lost += 0x10000L; 247 | packedSequenceNumber += 0x10000L; 248 | } 249 | else 250 | if (lost > 0x10000L/2) { 251 | lost -= 0x10000L; 252 | packedSequenceNumber -= 0x10000L; 253 | } 254 | 255 | if (lost < 0) { 256 | myPTRACE(lost == -1 ? 5 : 3, 257 | "T38modem\tT38ModemMediaStream::WritePacket: " << (packet.GetPayloadSize() == 0 ? "Fake" : "Repeated") << 258 | " packet " << packedSequenceNumber << " (expected " << currentSequenceNumber << ")"); 259 | 260 | if (lost > -10) 261 | return TRUE; 262 | } 263 | 264 | if (packet.GetPayloadSize() == 0) { 265 | myPTRACE(5, "T38Modem\tT38ModemMediaStream::WritePacket: ignored fake packet"); 266 | return TRUE; 267 | } 268 | 269 | PASN_OctetString ifp_packet((const char *)packet.GetPayloadPtr(), packet.GetPayloadSize()); 270 | 271 | T38_IFP ifp; 272 | 273 | if (!ifp_packet.DecodeSubType(ifp)) { 274 | myPTRACE(2, "T38Modem\tT38ModemMediaStream::WritePacket " T38_IFP_NAME " decode failure: " 275 | << PRTHEX(PBYTEArray(ifp_packet)) << "\n ifp = " 276 | << setprecision(2) << ifp); 277 | return TRUE; 278 | } 279 | 280 | if (lost != 0) { 281 | if (lost < 0 || lost > 10) 282 | lost = 1; 283 | 284 | #if PTRACING 285 | totallost += lost; 286 | #endif 287 | 288 | if (!t38engine->HandlePacketLost(EngineBase::HOWNERIN(this), lost)) 289 | return FALSE; 290 | 291 | myPTRACE(3, "T38Modem\tT38ModemMediaStream::WritePacket: adjusting sequence number to " << packedSequenceNumber); 292 | } 293 | 294 | currentSequenceNumber = packedSequenceNumber + 1; 295 | 296 | return t38engine->HandlePacket(EngineBase::HOWNERIN(this), ifp); 297 | } 298 | ///////////////////////////////////////////////////////////////////////////// 299 | 300 | -------------------------------------------------------------------------------- /t38engine.h: -------------------------------------------------------------------------------- 1 | /* 2 | * t38engine.h 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2001-2010 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): Equivalence Pty ltd 25 | * 26 | * $Log: t38engine.h,v $ 27 | * Revision 1.42 2010-10-12 16:46:25 vfrolov 28 | * Implemented fake streams 29 | * 30 | * Revision 1.42 2010/10/12 16:46:25 vfrolov 31 | * Implemented fake streams 32 | * 33 | * Revision 1.41 2010/10/06 16:54:19 vfrolov 34 | * Redesigned engine opening/closing 35 | * 36 | * Revision 1.40 2010/09/29 11:52:59 vfrolov 37 | * Redesigned engine attaching/detaching 38 | * 39 | * Revision 1.39 2010/09/22 15:39:19 vfrolov 40 | * Moved ResetModemState() to EngineBase 41 | * Replaced _ResetModemState() by OnResetModemState() 42 | * 43 | * Revision 1.38 2010/09/08 17:22:24 vfrolov 44 | * Redesigned modem engine (continue) 45 | * 46 | * Revision 1.37 2010/03/18 08:42:17 vfrolov 47 | * Added named tracing of data types 48 | * 49 | * Revision 1.36 2009/12/02 09:06:42 vfrolov 50 | * Added a short delay after transmitting of signal before call clearing 51 | * 52 | * Revision 1.35 2009/11/26 07:21:37 vfrolov 53 | * Added delay between transmitting of signals 54 | * 55 | * Revision 1.34 2009/11/19 14:48:28 vfrolov 56 | * Moved common code to class EngineBase 57 | * 58 | * Revision 1.33 2009/11/18 19:08:47 vfrolov 59 | * Moved common code to class EngineBase 60 | * 61 | * Revision 1.32 2009/11/10 08:13:38 vfrolov 62 | * Fixed race condition on re-opening T38Engine 63 | * 64 | * Revision 1.31 2009/11/06 10:19:29 vfrolov 65 | * Fixed indication handling after re-opening T38Engine 66 | * 67 | * Revision 1.30 2009/10/27 18:53:49 vfrolov 68 | * Added ability to re-open T38Engine 69 | * Added ability to prepare IFP packets with adaptive delay/period 70 | * 71 | * Revision 1.29 2009/07/27 16:21:24 vfrolov 72 | * Moved h323lib specific code to h323lib directory 73 | * 74 | * Revision 1.28 2008/09/24 14:51:45 frolov 75 | * Added 5 sec. timeout for DCE's transmit buffer empty 76 | * 77 | * Revision 1.27 2008/09/10 11:15:00 frolov 78 | * Ported to OPAL SVN trunk 79 | * 80 | * Revision 1.26 2007/05/10 10:40:33 vfrolov 81 | * Added ability to continuously resend last UDPTL packet 82 | * 83 | * Revision 1.25 2007/05/03 09:21:47 vfrolov 84 | * Added compile time optimization for original ASN.1 sequence 85 | * in T.38 (06/98) Annex A or for CORRIGENDUM No. 1 fix 86 | * 87 | * Revision 1.24 2007/04/11 14:19:15 vfrolov 88 | * Changed for OPAL 89 | * 90 | * Revision 1.23 2007/03/23 10:14:36 vfrolov 91 | * Implemented voice mode functionality 92 | * 93 | * Revision 1.22 2006/12/22 12:51:00 vfrolov 94 | * Fixed class of MutexModemCallback 95 | * Added volatile to isCarrierIn 96 | * Removed stateIn 97 | * 98 | * Revision 1.21 2006/12/11 11:19:48 vfrolov 99 | * Fixed race condition with modem Callback 100 | * 101 | * Revision 1.20 2005/07/20 12:42:36 vfrolov 102 | * Done less strict comparison in MODPARS::IsEqual() 103 | * 104 | * Revision 1.19 2005/07/18 11:39:48 vfrolov 105 | * Changed for OPAL 106 | * 107 | * Revision 1.18 2004/06/18 15:06:29 vfrolov 108 | * Fixed race condition by adding mutex for modemCallback 109 | * 110 | * Revision 1.17 2004/03/01 17:10:39 vfrolov 111 | * Fixed duplicated mutexes 112 | * Added volatile to T38Mode 113 | * 114 | * Revision 1.16 2003/12/04 16:10:05 vfrolov 115 | * Implemented FCS generation 116 | * Implemented ECM support 117 | * 118 | * Revision 1.15 2003/01/08 16:46:28 vfrolov 119 | * Added cbpOutBufNoFull and isOutBufFull() 120 | * Added data speed tracing 121 | * 122 | * Revision 1.14 2002/12/19 11:54:47 vfrolov 123 | * Removed DecodeIFPPacket() and utilized HandleRawIFP() 124 | * 125 | * Revision 1.13 2002/11/28 09:17:36 vfrolov 126 | * Added missing const 127 | * 128 | * Revision 1.12 2002/11/18 22:57:53 craigs 129 | * Added patches from Vyacheslav Frolov for CORRIGENDUM 130 | * 131 | * Revision 1.11 2002/05/22 12:01:50 vfrolov 132 | * Implemented redundancy error protection scheme 133 | * 134 | * Revision 1.10 2002/05/07 11:06:18 vfrolov 135 | * Discarded const from ModemCallbackWithUnlock() 136 | * 137 | * Revision 1.9 2002/05/07 10:15:44 vfrolov 138 | * Fixed dead lock on modemCallback 139 | * 140 | * Revision 1.8 2002/04/19 14:29:40 vfrolov 141 | * Added Copyright header 142 | * 143 | * Revision 1.7 2002/04/19 13:59:04 vfrolov 144 | * Added SendOnIdle() 145 | * 146 | * Revision 1.6 2002/02/11 16:46:21 vfrolov 147 | * Discarded transport arg from Originate() and Answer() 148 | * Thanks to Christopher Curtis 149 | * 150 | * Revision 1.5 2002/01/10 06:10:03 craigs 151 | * Added MPL header 152 | * 153 | * Revision 1.4 2002/01/06 03:48:45 craigs 154 | * Added changes to support efax 0.9 155 | * Thanks to Vyacheslav Frolov 156 | * 157 | * Revision 1.3 2002/01/03 21:36:42 craigs 158 | * Added additional logic to work with efax 159 | * Thanks to Vyacheslav Frolov 160 | * 161 | * Revision 1.2 2002/01/01 23:59:52 craigs 162 | * Lots of additional implementation thanks to Vyacheslav Frolov 163 | * 164 | */ 165 | 166 | #ifndef _T38ENGINE_H 167 | #define _T38ENGINE_H 168 | 169 | #include "pmutils.h" 170 | #include 171 | #include "hdlc.h" 172 | #include "t30.h" 173 | #include "enginebase.h" 174 | 175 | /////////////////////////////////////////////////////////////// 176 | class MODPARS 177 | { 178 | public: 179 | MODPARS( 180 | int _val = -1, 181 | unsigned _ind = unsigned(-1), 182 | int _lenInd = -1, 183 | unsigned _msgType = unsigned(-1), 184 | int _br = -1 185 | ); 186 | 187 | PBoolean IsModValid() const { return val >= 0; } 188 | PBoolean IsEqual(const MODPARS &mp) const { return msgType == mp.msgType; } 189 | 190 | EngineBase::DataType dataType; 191 | EngineBase::DataType dataTypeT38; 192 | int val; 193 | unsigned ind; 194 | int lenInd; 195 | unsigned msgType; 196 | int br; 197 | }; 198 | /////////////////////////////////////////////////////////////// 199 | #ifdef OPTIMIZE_CORRIGENDUM_IFP 200 | #define T38_IFP T38_IFPPacket 201 | #define T38_IFP_NAME "IFP" 202 | #else 203 | #define T38_IFP T38_PreCorrigendum_IFPPacket 204 | #define T38_IFP_NAME "Pre-corrigendum IFP" 205 | #endif 206 | /////////////////////////////////////////////////////////////// 207 | class ModStream; 208 | class T38_IFP; 209 | 210 | class T38Engine : public EngineBase 211 | { 212 | PCLASSINFO(T38Engine, EngineBase); 213 | 214 | public: 215 | 216 | enum { msPerOut = 30 }; 217 | 218 | /**@name Construction */ 219 | //@{ 220 | T38Engine(const PString &_name); 221 | ~T38Engine(); 222 | //@} 223 | 224 | /**@name Modem API */ 225 | //@{ 226 | virtual void SendOnIdle(DataType _dataType); 227 | virtual PBoolean SendStart(DataType _dataType, int param); 228 | virtual int Send(const void *pBuf, PINDEX count); 229 | virtual PBoolean SendStop(PBoolean moreFrames, int _callbackParam); 230 | virtual PBoolean isOutBufFull() const; 231 | virtual PBoolean SendingNotCompleted() const; 232 | 233 | virtual PBoolean RecvWait(DataType _dataType, int param, int _callbackParam, PBoolean &done); 234 | virtual PBoolean RecvStart(int _callbackParam); 235 | virtual int Recv(void *pBuf, PINDEX count); 236 | virtual void RecvStop(); 237 | virtual int RecvDiag() const; 238 | 239 | /**Prepare outgoing T.38 packet. 240 | 241 | If returns 0, then the writing loop should be terminated. 242 | If returns >0, then the ifp packet is correct and should be sent. 243 | If returns <0, then the ifp packet is not correct (timeout). 244 | */ 245 | int PreparePacket( 246 | HOWNEROUT hOwner, 247 | T38_IFP & ifp 248 | ); 249 | 250 | /**Set outgoing T.38 packet prepare timeout. 251 | */ 252 | void SetPreparePacketTimeout( 253 | HOWNEROUT hOwner, 254 | int timeout, 255 | int period = -1 256 | ); 257 | 258 | /**Handle incoming T.38 packet. 259 | 260 | If returns FALSE, then the reading loop should be terminated. 261 | */ 262 | PBoolean HandlePacket( 263 | HOWNERIN hOwner, 264 | const T38_IFP & ifp 265 | ); 266 | 267 | /**Handle lost T.38 packets. 268 | 269 | If returns FALSE, then the reading loop should be terminated. 270 | */ 271 | PBoolean HandlePacketLost( 272 | HOWNERIN hOwner, 273 | unsigned nLost 274 | ); 275 | //@} 276 | 277 | protected: 278 | virtual void OnAttach(); 279 | virtual void OnDetach(); 280 | virtual void OnResetModemState(); 281 | virtual void OnChangeModemClass(); 282 | virtual void OnOpenIn(); 283 | virtual void OnOpenOut(); 284 | virtual void OnCloseIn(); 285 | virtual void OnCloseOut(); 286 | virtual void OnChangeEnableFakeIn(); 287 | virtual void OnChangeEnableFakeOut(); 288 | 289 | private: 290 | void SignalOutDataReady() { outDataReadySyncPoint.Signal(); } 291 | void WaitOutDataReady() { outDataReadySyncPoint.Wait(); } 292 | PBoolean WaitOutDataReady(const PTimeInterval & timeout) { 293 | return outDataReadySyncPoint.Wait(timeout); 294 | } 295 | 296 | private: 297 | DataStream bufOut; 298 | 299 | int preparePacketTimeout; 300 | int preparePacketPeriod; 301 | 302 | PAdaptiveDelay preparePacketDelay; 303 | 304 | int stateOut; 305 | DataType onIdleOut; 306 | int callbackParamOut; 307 | MODPARS ModParsOut; 308 | PBoolean delaySignalOut; 309 | PBoolean startedTimeOutBufEmpty; 310 | PTime timeOutBufEmpty; 311 | PTime timeDelayEndOut; 312 | PTime timeBeginOut; 313 | PINDEX countOut; 314 | PBoolean moreFramesOut; 315 | HDLC hdlcOut; 316 | 317 | int callbackParamIn; 318 | volatile int isCarrierIn; 319 | #if PTRACING 320 | PTime timeBeginIn; 321 | #endif 322 | PINDEX countIn; 323 | 324 | T30 t30; 325 | 326 | ModStream *modStreamIn; 327 | ModStream *modStreamInSaved; 328 | 329 | volatile int stateModem; 330 | 331 | PSyncPoint outDataReadySyncPoint; 332 | }; 333 | /////////////////////////////////////////////////////////////// 334 | 335 | #endif // _T38ENGINE_H 336 | 337 | -------------------------------------------------------------------------------- /hdlc.cxx: -------------------------------------------------------------------------------- 1 | /* 2 | * hdlc.cxx 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2003-2010 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): Equivalence Pty ltd 25 | * 26 | * $Log: hdlc.cxx,v $ 27 | * Revision 1.8 2010-10-08 06:06:39 vfrolov 28 | * Added diagErrorMask 29 | * 30 | * Revision 1.8 2010/10/08 06:06:39 vfrolov 31 | * Added diagErrorMask 32 | * 33 | * Revision 1.7 2009/11/09 19:12:57 vfrolov 34 | * Changed T38Engine to EngineBase 35 | * 36 | * Revision 1.6 2008/09/10 11:15:00 frolov 37 | * Ported to OPAL SVN trunk 38 | * 39 | * Revision 1.5 2005/02/03 11:32:11 vfrolov 40 | * Fixed MSVC compile warnings 41 | * 42 | * Revision 1.4 2004/07/06 16:07:24 vfrolov 43 | * Included ptlib.h for precompiling 44 | * 45 | * Revision 1.3 2004/03/09 12:52:39 vfrolov 46 | * Fixed compile warning 47 | * 48 | * Revision 1.2 2004/02/17 13:23:07 vfrolov 49 | * Fixed MSVC compile errors 50 | * 51 | * Revision 1.1 2003/12/04 13:38:33 vfrolov 52 | * Initial revision 53 | * 54 | */ 55 | 56 | #include 57 | #include "hdlc.h" 58 | #include "enginebase.h" 59 | 60 | /////////////////////////////////////////////////////////////// 61 | 62 | #define new PNEW 63 | 64 | /////////////////////////////////////////////////////////////// 65 | void HDLC::pack(const void *_pBuf, PINDEX count, PBoolean flag) 66 | { 67 | WORD w = WORD((WORD)rawByte << 8); 68 | const BYTE *pBuf = (const BYTE *)_pBuf; 69 | 70 | for (PINDEX i = 0 ; i < count ; i++) { 71 | w |= *(pBuf++) & 0xFF; 72 | for (PINDEX j = 0 ; j < 8 ; j++) { 73 | w <<= 1; 74 | 75 | if (++rawByteLen == 8) { 76 | rawByte = BYTE(w >> 8); 77 | outData.PutData(&rawByte, 1); 78 | rawByteLen = 0; 79 | } 80 | 81 | if (!flag) { 82 | if (w & 0x100) { 83 | if (++rawOnes == 5) { 84 | w = WORD((w & 0xFF00) << 1 | (w & 0xFF)); 85 | 86 | if (++rawByteLen == 8) { 87 | rawByte = BYTE(w >> 8); 88 | outData.PutData(&rawByte, 1); 89 | rawByteLen = 0; 90 | } 91 | rawOnes = 0; 92 | } 93 | } 94 | else 95 | rawOnes = 0; 96 | } 97 | } 98 | } 99 | rawByte = BYTE(w >> 8); 100 | if (flag) 101 | rawOnes = 0; 102 | } 103 | 104 | PBoolean HDLC::sync(BYTE b) 105 | { 106 | WORD w = WORD(((WORD)rawByte << 8) | (b & 0xFF)); 107 | PINDEX j = 8 - rawByteLen; 108 | 109 | w <<= j; 110 | 111 | for ( ; j <= 8 ; j++, w <<= 1) { 112 | if ((w >> 8) == 0x7E) { 113 | rawByte = BYTE(w >> j); 114 | rawByteLen = 8 - j; 115 | return TRUE; 116 | } 117 | } 118 | rawByte = BYTE(w >> j); 119 | rawByteLen = 7; 120 | return FALSE; 121 | } 122 | 123 | PBoolean HDLC::skipFlag(BYTE b) 124 | { 125 | WORD w = WORD(((WORD)rawByte << 8) | (b & 0xFF)); 126 | PINDEX j = 8 - rawByteLen; 127 | 128 | w <<= j; 129 | if ((w >> 8) == 0x7E) { 130 | rawByte = BYTE(w >> j); 131 | return TRUE; 132 | } 133 | 134 | return FALSE; 135 | } 136 | 137 | PBoolean HDLC::unpack(BYTE b) 138 | { 139 | //myPTRACE(1, "T38Modem\tunpack det " << hex << (WORD)b); 140 | WORD w = WORD(((WORD)rawByte << 8) | (b & 0xFF)); 141 | PINDEX j = 8 - rawByteLen; 142 | 143 | w <<= j; 144 | 145 | for ( ; j <= 8 ; j++, w <<= 1) { 146 | if ((w >> 8) == 0x7E) { 147 | rawByte = BYTE(w >> j); 148 | rawByteLen = 8 - j; 149 | return FALSE; 150 | } 151 | 152 | if (w & 0x8000) { 153 | hdlcChunk <<= 1; 154 | hdlcChunk |= 1; 155 | hdlcChunkLen++; 156 | rawOnes++; 157 | } else { 158 | if (rawOnes != 5) { 159 | hdlcChunk <<= 1; 160 | hdlcChunkLen++; 161 | } 162 | rawOnes = 0; 163 | } 164 | 165 | if (hdlcChunkLen == 24) { 166 | BYTE b = BYTE(hdlcChunk >> 16); 167 | outData.PutData(&b, 1); 168 | //myPTRACE(1, "T38Modem\tunpack put " << hex << (WORD)hdlcChunk); 169 | hdlcChunkLen = 16; 170 | } 171 | } 172 | rawByte = BYTE(w >> j); 173 | rawByteLen = 7; 174 | return TRUE; 175 | } 176 | /////////////////////////////////////////////////////////////// 177 | int HDLC::GetInData(void *pBuf, PINDEX count) 178 | { 179 | if (!inData) 180 | return -1; 181 | 182 | int len = inData->GetData(pBuf, count); 183 | 184 | if (len > 0) { 185 | rawCount += len; 186 | lastChar = ((BYTE *)pBuf)[len - 1]; 187 | } else 188 | if (len < 0) { 189 | inData = NULL; 190 | return -1; 191 | } 192 | return len; 193 | } 194 | 195 | int HDLC::GetRawData(void *_pBuf, PINDEX count) 196 | { 197 | BYTE *pBuf = (BYTE *)_pBuf; 198 | 199 | switch (inDataType) { 200 | case EngineBase::dtHdlc: 201 | break; 202 | case EngineBase::dtRaw: 203 | return GetInData(pBuf, count); 204 | default: 205 | return 0; 206 | } 207 | 208 | int outLen = outData.GetData(pBuf, count); 209 | 210 | if (outLen < 0) 211 | return -1; 212 | 213 | int len = 0; 214 | 215 | if (outLen > 0) { 216 | pBuf += outLen; 217 | count -= outLen; 218 | len += outLen; 219 | } 220 | 221 | do { 222 | if (inData) { 223 | BYTE Buf[256]; 224 | int inLen = inData->GetData(Buf, sizeof(Buf)); 225 | 226 | if (inLen < 0) { 227 | Buf[0] = BYTE(fcs >> 8); 228 | Buf[1] = BYTE(fcs & 0xFF); 229 | if (inData->GetDiag() & EngineBase::diagErrorMask) 230 | Buf[0]++; 231 | pack(Buf, 2); 232 | pack("\x7e\x7e", 2, TRUE); 233 | outData.PutEof(); 234 | inData = NULL; 235 | } 236 | else 237 | if (inLen > 0) { 238 | lastChar = Buf[inLen - 1]; 239 | fcs.build(Buf, inLen); 240 | pack(Buf, inLen); 241 | } 242 | else 243 | break; 244 | } 245 | 246 | int outLen = outData.GetData(pBuf, count); 247 | 248 | if (outLen < 0) { 249 | if (len > 0) 250 | break; 251 | return -1; 252 | } 253 | else 254 | if (outLen > 0) { 255 | pBuf += outLen; 256 | count -= outLen; 257 | len += outLen; 258 | } 259 | } while (count); 260 | 261 | if (len > 0) 262 | rawCount += len; 263 | 264 | return len; 265 | } 266 | 267 | int HDLC::GetHdlcData(void *_pBuf, PINDEX count) 268 | { 269 | int len; 270 | BYTE *pBuf = (BYTE *)_pBuf; 271 | 272 | switch (inDataType) { 273 | case EngineBase::dtHdlc: 274 | len = GetInData(pBuf, count); 275 | if (len > 0) 276 | fcs.build(pBuf, len); 277 | return len; 278 | case EngineBase::dtRaw: 279 | break; 280 | default: 281 | return 0; 282 | } 283 | 284 | if (!inData || hdlcState == stEof) { 285 | len = outData.GetData(pBuf, count); 286 | if (len > 0) 287 | fcs.build(pBuf, len); 288 | } 289 | else 290 | if (!count && hdlcState == stData) { 291 | if (outData.GetData(NULL, 0) < 0 || inData->GetData(NULL, 0) < 0) 292 | return -1; 293 | return 0; 294 | } else { 295 | BYTE b; 296 | int res; 297 | len = 0; 298 | 299 | for ( ; (res = inData->GetData(&b, 1)) != 0 ; ) { 300 | if (res < 0) { 301 | outData.PutEof(); 302 | inData = NULL; 303 | hdlcState = stEof; 304 | //myPTRACE(1, "T38Modem\thdlcState=stEof EOF"); 305 | } 306 | else { 307 | lastChar = b; 308 | rawCount++; 309 | switch (hdlcState) { 310 | case stSync: 311 | if (sync(b)) { 312 | hdlcState = stSkipFlags; 313 | //myPTRACE(1, "T38Modem\thdlcState=stSkipFlags " << hex << (int)b); 314 | } 315 | break; 316 | case stSkipFlags: 317 | if (skipFlag(b)) 318 | break; 319 | hdlcState = stData; 320 | //myPTRACE(1, "T38Modem\thdlcState=stData " << hex << (int)b); 321 | case stData: 322 | if (!unpack(b)) { 323 | outData.PutEof(); 324 | hdlcState = stEof; 325 | //myPTRACE(1, "T38Modem\thdlcState=stEof " << hex << (int)b); 326 | } 327 | break; 328 | default: 329 | myPTRACE(1, "T38Modem\tHDLC::GetHdlcData(): unexpected hdlcState=" << hdlcState); 330 | } 331 | } 332 | 333 | if (hdlcState == stEof || hdlcState == stData) { 334 | int outLen = outData.GetData(pBuf, count); 335 | 336 | if (outLen < 0) { 337 | if (len > 0) 338 | break; 339 | return -1; 340 | } 341 | else 342 | if (outLen > 0) { 343 | fcs.build(pBuf, outLen); 344 | pBuf += outLen; 345 | count -= outLen; 346 | len += outLen; 347 | } 348 | if (!count || hdlcState == stEof) 349 | break; 350 | } 351 | } 352 | } 353 | 354 | return len; 355 | } 356 | /////////////////////////////////////////////////////////////// 357 | HDLC::HDLC() : 358 | inDataType(EngineBase::dtNone), outDataType(EngineBase::dtNone), 359 | inData(NULL), lastChar(-1), rawCount(0), 360 | rawByteLen(0), rawOnes(0), hdlcState(stEof) 361 | { 362 | } 363 | 364 | PBoolean HDLC::isFcsOK() 365 | { 366 | if (hdlcChunkLen != 16) { 367 | myPTRACE(1, "T38Modem\tisFcsOK(): hdlcChunkLen(" << hdlcChunkLen << ") != 16"); 368 | return FALSE; 369 | } 370 | 371 | if ((WORD)hdlcChunk != fcs) { 372 | myPTRACE(1, "T38Modem\tisFcsOK(): hdlcChunk(" << hex << (WORD)hdlcChunk << ") != fcs(" << (WORD)fcs << ")"); 373 | return FALSE; 374 | } 375 | 376 | return TRUE; 377 | } 378 | 379 | void HDLC::PutRawData(DataStream *_inData) 380 | { 381 | inDataType = EngineBase::dtRaw; 382 | inData = _inData; 383 | lastChar = -1; 384 | } 385 | 386 | void HDLC::PutHdlcData(DataStream *_inData) 387 | { 388 | inDataType = EngineBase::dtHdlc; 389 | inData = _inData; 390 | lastChar = -1; 391 | } 392 | 393 | void HDLC::GetRawStart(PINDEX flags) 394 | { 395 | outDataType = EngineBase::dtRaw; 396 | outData.Clean(); 397 | fcs = FCS(); 398 | if (inDataType == EngineBase::dtHdlc) { 399 | while (flags--) 400 | pack("\x7e", 1, TRUE); 401 | } 402 | } 403 | 404 | void HDLC::GetHdlcStart(PBoolean sync) 405 | { 406 | outDataType = EngineBase::dtHdlc; 407 | outData.Clean(); 408 | fcs = FCS(); 409 | if (inDataType == EngineBase::dtRaw) { 410 | hdlcChunkLen = 0; 411 | rawOnes = 0; 412 | hdlcState = sync ? stSync : stSkipFlags; 413 | } else { 414 | if (!sync) 415 | rawCount += 4; // count FCS, flags, zeros 416 | } 417 | //myPTRACE(1, "T38Modem\thdlcState=" << (sync ? "stSync" : "stSkipFlags") << " START"); 418 | } 419 | 420 | int HDLC::GetData(void *pBuf, PINDEX count) 421 | { 422 | switch (outDataType) { 423 | case EngineBase::dtHdlc: 424 | return GetHdlcData(pBuf, count); 425 | case EngineBase::dtRaw: 426 | return GetRawData(pBuf, count); 427 | default: 428 | myPTRACE(1, "T38Modem\tHDLC::GetData bad outDataType=" << outDataType); 429 | } 430 | return -1; 431 | } 432 | /////////////////////////////////////////////////////////////// 433 | 434 | -------------------------------------------------------------------------------- /ReadMe.txt: -------------------------------------------------------------------------------- 1 | /* 2 | * README 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Original author: Vyacheslav Frolov 7 | * 8 | * Additional contributors: Henning Holtschneider, Pete Davidson 9 | * 10 | */ 11 | 12 | 1. Introduction 13 | --------------- 14 | 15 | What is t38modem? 16 | 17 | From your fax or voice application view point it's a fax/voice modem pool. 18 | From IP network view point it's a H.323/SIP endpoint with T.38 fax support. 19 | From your view point it's a gateway between an application and IP network. 20 | 21 | The homepage for t38modem project is http://t38modem.sourceforge.net/. 22 | 23 | T38modem version 2.0.0 can only be used with opal/ptlib revision 24174. 24 | 25 | To use later versions of opal/ptlib see the t38modem projects at github: 26 | https://github.com/hehol/t38modem 27 | https://github.com/PeteDavidson/t38modem 28 | 29 | 2. Building 30 | ----------- 31 | 32 | 2.1. Building for Unix 33 | ---------------------- 34 | 35 | Building with Open Phone Abstraction Library (OPAL): 36 | 37 | $ export PTLIBDIR=$path_to_libs/ptlib 38 | $ export OPALDIR=$path_to_libs/opal 39 | $ make USE_OPAL=1 opt 40 | 41 | 2.2. Building for Windows 42 | ------------------------- 43 | 44 | Building with Open Phone Abstraction Library (OPAL): 45 | 46 | Start Microsoft Visual C++ 2005 with opal\t38modem_2005.vcproj file. 47 | Set Active Configuration to "t38modem - Win32 Release". 48 | Build t38modem.exe. 49 | 50 | 3. Examples 51 | ----------- 52 | 53 | To get info about t38modem command line syntax enter: 54 | 55 | $ t38modem --help 56 | 57 | 58 | 3.1. Starting 59 | ------------- 60 | 61 | Starting with Open H323 Library or H323 Plus Library: 62 | 63 | $ t38modem -n -o trace.log -p ttyx0,ttyx1 --old-asn \ 64 | --route 0@127.0.0.1 --route all@172.16.33.21 65 | 66 | This will create two modems (/dev/ttyx0 and /dev/ttyx1) and H.323 endpoint. 67 | If dialed number begins with '0' then it will be routed to a local host 68 | (leading '0' will be discarded). Other dialed numbers will be routed to 69 | 172.16.33.21. 70 | 71 | Starting with OPAL: 72 | 73 | $ t38modem -n -o trace.log -p ttyx0,ttyx1 \ 74 | --route "modem:0.*=h323:@127.0.0.1" \ 75 | --route "modem:1.*=sip:@172.16.33.20" \ 76 | --route "modem:2.*=h323:@172.16.33.21" \ 77 | --route "h323:.*=modem:" \ 78 | --route "sip:.*=modem:" 79 | 80 | This will create two modems (/dev/ttyx0 and /dev/ttyx1) and H.323 and SIP endpoints. 81 | If dialed number begins with '0' then it will be routed to a local host. 82 | If dialed number begins with '1' then it will be routed to SIP endpoint 172.16.33.20. 83 | If dialed number begins with '2' then it will be routed to H.323 endpoint 172.16.33.21. 84 | Leading '0', '1' and '2' will be discarded. 85 | 86 | Q. I try to use T38modem, but after run "t38modem -p ttyx0" I get a message 87 | "Could not open /dev/ptyx0: No such file or directory". 88 | A. Looks like you don't have legacy PTY devices compiled in your kernel. 89 | You need to re-compile the kernel with 'Legacy PTY Support'. 90 | Alternatively, you can build t38modem with USE_UNIX98_PTY=1 option and use 91 | -p +/dev/ttyx0,+/dev/ttyx1 instead of -p ttyx0,ttyx1. 92 | 93 | FreeBSD Users: You need to use -p ttypa,ttypb instead of -p ttyx0,ttyx1. 94 | Remember to replace ttyx0 with ttypa and ttyx1 with ttypb 95 | when following the rest of these instructions. 96 | This will create two modems /dev/ttypa and /dev/ttypb. 97 | 98 | Windows Users: You need two COM ports connected via Null-modem cable to create one modem. 99 | If your COM1 connected to COM2 and COM3 connected to COM4 you need to use 100 | -p \\.\COM2,\\.\COM4 instead of -p ttyx0,ttyx1. 101 | This will create two modems COM1 and COM3. 102 | Q. How to use t38modem without additional COM port hardware on Windows? 103 | A. Replace a pair of physical COM ports with a pair of virtual COM ports. 104 | See http://com0com.sourceforge.net/ project for details. 105 | Q. What model of modem to select in Add Hardware Wizard? 106 | A. Select "Standard 1440 bps Modem". 107 | 108 | Cisco Users: Possible additionaly you will need to use --h245tunneldisable option. 109 | 110 | 3.2. Testing (you need two consoles) 111 | ------------------------------------ 112 | (FreeBSD users - remeber to use /dev/ttypa and /dev/ttypb with 'cu -l') 113 | (Windows users - use COM1 and COM3 with HyperTerminal) 114 | 115 | $ cu -l /dev/ttyx0 $ cu -l /dev/ttyx1 116 | Connected. Connected. 117 | <-- at <-- at 118 | --> OK --> OK 119 | (wait at least 10 secs) 120 | <-- atdt012345 121 | 122 | --> 123 | --> RING 124 | --> 125 | --> RING 126 | <-- ati9 127 | --> NDID = 12345 128 | --> OK 129 | --> 130 | --> RING 131 | --> 132 | --> RING 133 | <-- ata 134 | --> CONNECT --> CONNECT 135 | <-- x 136 | --> OK 137 | <-- ath 138 | --> OK 139 | --> 140 | --> ERROR 141 | <-- at 142 | --> OK 143 | <-- at 144 | --> OK 145 | ... ... 146 | 147 | 148 | 3.3. Example of Cisco config (loopback) 149 | --------------------------------------- 150 | 151 | 10.0.2.12 --> Cisco port 2:D --E1-cable--> Cisco port 3:D --> 10.0.2.12 152 | 153 | dial-peer voice 3340 voip 154 | incoming called-number 3334.... 155 | codec g711alaw 156 | fax rate 14400 157 | fax protocol t38 ls-redundancy 0 hs-redundancy 0 158 | 159 | dial-peer voice 3341 pots 160 | destination-pattern 3334.... 161 | port 2:D 162 | forward-digits 7 163 | 164 | dial-peer voice 3342 pots 165 | incoming called-number 334.... 166 | direct-inward-dial 167 | port 3:D 168 | exit 169 | 170 | dial-peer voice 3343 voip 171 | destination-pattern 334.... 172 | session target ipv4:10.0.2.12 173 | codec g711alaw 174 | fax rate 14400 175 | fax protocol t38 ls-redundancy 0 hs-redundancy 0 176 | exit 177 | 178 | 3.4. Example of HylaFAX modem config files 179 | ------------------------------------------ 180 | 181 | Copy HylaFAX/etc/config.ttyx to HylaFAX's etc directory 182 | 183 | Create simbolic links: 184 | 185 | config.ttyx0 -> config.ttyx 186 | config.ttyx1 -> config.ttyx 187 | 188 | Start HylaFAX with new modems: 189 | 190 | $ .../faxgetty -D ttyx0 191 | $ .../faxgetty -D ttyx1 192 | 193 | (FreeBSD users - don't forget we are using ttypa and ttypb) 194 | 195 | 4. AT commands specific to t38modem 196 | ----------------------------------- 197 | 198 | 4.1. AT#CID command 199 | ------------------- 200 | 201 | 4.1.1 Reporting Caller ID and DID after the first RING 202 | ------------------------------------------------------ 203 | 204 | #CID=0 - disable Caller ID and DID reporting (default). 205 | #CID=1 - enable only Caller ID reporting. 206 | #CID=10 - enable Caller ID and DID reporting. 207 | #CID=11 - enable only DID reporting. 208 | 209 | Example: 210 | 211 | <-- AT#CID=10 212 | --> OK 213 | --> RING 214 | --> DATE = ; Caller ID 215 | --> TIME = ; Caller ID 216 | --> NMBR = ; Caller ID 217 | --> NAME = ; Caller ID 218 | --> NDID = ; DID 219 | --> RING 220 | --> RING 221 | 222 | 4.2. ATI command 223 | ---------------- 224 | 225 | 4.2.1 calling/called number reporting 226 | ------------------------------------- 227 | 228 | I8 - reports calling number for last incoming call. 229 | I9 - reports called number for last incoming call. 230 | 231 | Example: 232 | 233 | <-- ATI8I9 234 | --> NMBR = 235 | --> NDID = 236 | --> OK 237 | 238 | 4.3. ATD command 239 | ---------------- 240 | 241 | 4.3.1 Fax mode modifiers 242 | ------------------------ 243 | 244 | F - force fax mode (T.38 or G.711 pass-trough) after dialing 245 | (with OPAL can be overridden by route option OPAL-Force-Fax-Mode=false). 246 | V - do not force fax mode after dialing (default) 247 | (with OPAL can be overridden by route option OPAL-Force-Fax-Mode=true). 248 | 249 | Examples: 250 | 251 | <-- ATDF 252 | 253 | force fax mode after dialing but user can override it by 254 | inserting V into . 255 | 256 | <-- ATDV 257 | 258 | do not force fax mode after dialing and user can't override it 259 | by inserting F into . 260 | 261 | 4.3.2 calling/called number modifiers 262 | ------------------------------------- 263 | 264 | L - purge calling number and start dialing it. 265 | T,P,D - continue to dial of called number if dialing of calling number was started. 266 | 267 | If calling number is empty after processing ATD command then t38modem's 268 | local party number used. 269 | 270 | The calling number is a string of 0 or more of the characters: 271 | 272 | "0 1 2 3 4 5 6 7 8 9 * #" 273 | 274 | Note: dialing of calling number is not allowed in online command state. 275 | 276 | The called number is a string of 0 or more of the characters: 277 | 278 | "0 1 2 3 4 5 6 7 8 9 * # + A B C D" 279 | 280 | Note: '+' will be ignored in online command state or after '@' modifier. 281 | 282 | Examples: 283 | 284 | <-- ATD 285 | 286 | calling number is t38modem's local party number but user can override 287 | it by inserting L into 288 | 289 | <-- ATDL 290 | 291 | calling number is t38modem's local party number and user can't override 292 | it by inserting L into 293 | 294 | <-- ATDLT 295 | 296 | calling number is but user can override 297 | it by inserting L into 298 | 299 | <-- ATDL 300 | 301 | calling number is and user can't override 302 | it by inserting L into 303 | 304 | 4.3.3 Wait for answer modifier 305 | ------------------------------ 306 | 307 | @ - dial the called number part collected before first @, wait till the call 308 | answered and play the called number part collected after last @. 309 | Implicitly '@' will continue dialing of called number (see 4.3.2). 310 | 311 | Examples: 312 | 313 | <-- ATS8? 314 | --> 002 315 | --> OK 316 | <-- ATD12345@,,,4321 317 | 318 | dial number 12345, wait till the call answered, wait 6 seconds 319 | (3 commas * 2 seconds), play digits 4321. 320 | 321 | <-- ATD12345@,,,4321@ 322 | 323 | dial number 12345. 324 | 325 | 4.4. AT#DFRMC command 326 | --------------------- 327 | 328 | 4.4.1 Set delay for CONNECT result code for AT+FRM command 329 | ---------------------------------------------------------- 330 | 331 | #DFRMC=0 - disable delay (default). 332 | #DFRMC=25 - set delay to 250 ms. 333 | 334 | 4.5. AT#HCLR command 335 | -------------------- 336 | 337 | 4.5.1 Set clear call mode for ATH command 338 | ----------------------------------------- 339 | 340 | #HCLR=0 - ATH command will not clear not answered incoming call (default). 341 | #HCLR=1 - ATH command will clear not answered incoming call. 342 | 343 | 4.6. AT#CIDFMT command 344 | ---------------------- 345 | 346 | AT#CIDFMT command allows to set value format for NAME and NMBR tags of Caller ID. 347 | 348 | Syntax: 349 | 350 | #CIDFMT=[][,[]] 351 | 352 | If a format element is empty then its value will be untouched. 353 | 354 | Subparameter : 355 | 356 | 0 - report "NAME = " (default) 357 | 1 - report "NAME = " 358 | 2 - report "NAME = " 359 | 3 - report "NAME = <- " 360 | 361 | Subparameter : 362 | 363 | 0 - report "NMBR = " (default) 364 | 1 - report "NMBR = " 365 | 2 - report "NMBR = " 366 | 3 - report "NMBR = #" 367 | 368 | -------------------------------------------------------------------------------- /enginebase.cxx: -------------------------------------------------------------------------------- 1 | /* 2 | * enginebase.cxx 3 | * 4 | * T38FAX Pseudo Modem 5 | * 6 | * Copyright (c) 2007-2010 Vyacheslav Frolov 7 | * 8 | * Open H323 Project 9 | * 10 | * The contents of this file are subject to the Mozilla Public License 11 | * Version 1.0 (the "License"); you may not use this file except in 12 | * compliance with the License. You may obtain a copy of the License at 13 | * http://www.mozilla.org/MPL/ 14 | * 15 | * Software distributed under the License is distributed on an "AS IS" 16 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 | * the License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * The Original Code is Open H323 Library. 21 | * 22 | * The Initial Developer of the Original Code is Vyacheslav Frolov 23 | * 24 | * Contributor(s): 25 | * 26 | * $Log: enginebase.cxx,v $ 27 | * Revision 1.13 2010-10-12 16:46:25 vfrolov 28 | * Implemented fake streams 29 | * 30 | * Revision 1.13 2010/10/12 16:46:25 vfrolov 31 | * Implemented fake streams 32 | * 33 | * Revision 1.12 2010/10/06 16:54:19 vfrolov 34 | * Redesigned engine opening/closing 35 | * 36 | * Revision 1.11 2010/09/29 11:52:59 vfrolov 37 | * Redesigned engine attaching/detaching 38 | * 39 | * Revision 1.10 2010/09/22 15:07:45 vfrolov 40 | * Added ResetModemState() and OnResetModemState() 41 | * 42 | * Revision 1.9 2010/09/08 17:22:23 vfrolov 43 | * Redesigned modem engine (continue) 44 | * 45 | * Revision 1.8 2010/07/07 08:09:47 vfrolov 46 | * Added IsAttached() 47 | * 48 | * Revision 1.7 2010/03/18 08:42:17 vfrolov 49 | * Added named tracing of data types 50 | * 51 | * Revision 1.6 2009/11/19 14:48:28 vfrolov 52 | * Moved common code to class EngineBase 53 | * 54 | * Revision 1.5 2009/11/19 11:14:04 vfrolov 55 | * Added OnUserInput 56 | * 57 | * Revision 1.4 2009/11/18 19:08:47 vfrolov 58 | * Moved common code to class EngineBase 59 | * 60 | * Revision 1.3 2008/09/10 11:15:00 frolov 61 | * Ported to OPAL SVN trunk 62 | * 63 | * Revision 1.2 2007/04/09 08:07:12 vfrolov 64 | * Added symbolic logging ModemCallbackParam 65 | * 66 | * Revision 1.1 2007/03/23 09:54:45 vfrolov 67 | * Initial revision 68 | * 69 | */ 70 | 71 | #include 72 | #include "pmutils.h" 73 | #include "enginebase.h" 74 | 75 | #define new PNEW 76 | 77 | /////////////////////////////////////////////////////////////// 78 | #if PTRACING 79 | ostream & operator<<(ostream & out, EngineBase::DataType dataType) 80 | { 81 | switch (dataType) { 82 | case EngineBase::dtNone: return out << "dtNone"; 83 | case EngineBase::dtRing: return out << "dtRing"; 84 | case EngineBase::dtBusy: return out << "dtBusy"; 85 | case EngineBase::dtCed: return out << "dtCed"; 86 | case EngineBase::dtCng: return out << "dtCng"; 87 | case EngineBase::dtSilence: return out << "dtSilence"; 88 | case EngineBase::dtHdlc: return out << "dtHdlc"; 89 | case EngineBase::dtRaw: return out << "dtRaw"; 90 | } 91 | 92 | return out << "dt" << INT(dataType); 93 | } 94 | 95 | ostream & operator<<(ostream & out, EngineBase::ModemCallbackParam param) 96 | { 97 | switch (param) { 98 | case EngineBase::cbpUserDataMask: break; 99 | case EngineBase::cbpOutBufNoFull: return out << "cbpOutBufNoFull"; 100 | case EngineBase::cbpUpdateState: return out << "cbpUpdateState"; 101 | case EngineBase::cbpReset: return out << "cbpReset"; 102 | case EngineBase::cbpOutBufEmpty: return out << "cbpOutBufEmpty"; 103 | case EngineBase::cbpUserInput: return out << "cbpUserInput"; 104 | } 105 | 106 | return out << "cbp" << INT(param); 107 | } 108 | 109 | ostream & operator<<(ostream & out, EngineBase::ModemClass modemClass) 110 | { 111 | switch (modemClass) { 112 | case EngineBase::mcUndefined: return out << "mcUndefined"; 113 | case EngineBase::mcFax: return out << "mcFax"; 114 | } 115 | 116 | return out << "mc" << INT(modemClass); 117 | } 118 | #endif 119 | /////////////////////////////////////////////////////////////// 120 | EngineBase::EngineBase(const PString &_name) 121 | : name(_name) 122 | , recvUserInput(NULL) 123 | , modemClass(mcUndefined) 124 | , hOwnerIn(NULL) 125 | , hOwnerOut(NULL) 126 | , firstIn(TRUE) 127 | , firstOut(TRUE) 128 | , isFakeOwnerIn(FALSE) 129 | , isFakeOwnerOut(FALSE) 130 | , isEnableFakeIn(FALSE) 131 | , isEnableFakeOut(FALSE) 132 | { 133 | } 134 | 135 | EngineBase::~EngineBase() 136 | { 137 | if (recvUserInput) 138 | delete recvUserInput; 139 | 140 | if (hOwnerIn != NULL) 141 | myPTRACE(1, "T38Modem\t" << name << " ~EngineBase WARNING: (In) still open by " << hOwnerIn); 142 | 143 | if (hOwnerOut != NULL) 144 | myPTRACE(1, "T38Modem\t" << name << " ~EngineBase WARNING: (Out) still open by " << hOwnerOut); 145 | 146 | if (!modemCallback.IsNULL()) 147 | myPTRACE(1, "T38Modem\t" << name << " ~EngineBase WARNING: !modemCallback.IsNULL()"); 148 | } 149 | 150 | PBoolean EngineBase::Attach(const PNotifier &callback) 151 | { 152 | myPTRACE(1, "T38Modem\t" << name << " Attach"); 153 | 154 | PWaitAndSignal mutexWait(Mutex); 155 | 156 | if (!modemCallback.IsNULL()) { 157 | myPTRACE(1, "T38Modem\t" << name << " Attach !modemCallback.IsNULL()"); 158 | 159 | return FALSE; 160 | } 161 | 162 | modemCallback = callback; 163 | 164 | OnAttach(); 165 | 166 | return TRUE; 167 | } 168 | 169 | void EngineBase::OnAttach() 170 | { 171 | myPTRACE(1, "T38Modem\t" << name << " OnAttach Attached"); 172 | 173 | OnResetModemState(); 174 | } 175 | 176 | void EngineBase::Detach(const PNotifier &callback) 177 | { 178 | myPTRACE(1, "T38Modem\t" << name << " Detach"); 179 | 180 | PWaitAndSignal mutexWait(Mutex); 181 | 182 | if (modemCallback.IsNULL()) { 183 | myPTRACE(1, "T38Modem\t" << name << " Detach Already Detached"); 184 | 185 | return; 186 | } 187 | 188 | if (modemCallback != callback) { 189 | myPTRACE(1, "T38Modem\t" << name << " Detach modemCallback != callback"); 190 | 191 | return; 192 | } 193 | 194 | modemCallback = NULL; 195 | modemClass = mcUndefined; 196 | 197 | OnChangeModemClass(); 198 | OnDetach(); 199 | } 200 | 201 | void EngineBase::OnDetach() 202 | { 203 | myPTRACE(1, "T38Modem\t" << name << " OnDetach Detached"); 204 | 205 | OnResetModemState(); 206 | } 207 | 208 | void EngineBase::ResetModemState() { 209 | PWaitAndSignal mutexWaitModem(MutexModem); 210 | PWaitAndSignal mutexWait(Mutex); 211 | 212 | OnResetModemState(); 213 | } 214 | 215 | void EngineBase::OnResetModemState() 216 | { 217 | myPTRACE(1, "T38Modem\t" << name << " OnResetModemState"); 218 | } 219 | 220 | void EngineBase::OpenIn(HOWNERIN hOwner, PBoolean fake) 221 | { 222 | PWaitAndSignal mutexWait(Mutex); 223 | 224 | while (hOwnerIn != NULL) { 225 | if (hOwnerIn == hOwner) { 226 | myPTRACE(1, "T38Modem\t" << name << " OpenIn: re-open " << hOwner); 227 | return; 228 | } 229 | 230 | if (fake) { 231 | myPTRACE(1, "T38Modem\t" << name << " OpenIn: disabled close " << hOwnerIn << " by fake " << hOwner); 232 | return; 233 | } 234 | 235 | myPTRACE(1, "T38Modem\t" << name << " OpenIn " << (isFakeOwnerIn ? ": close fake " : "WARNING: close ") << hOwnerIn << " by " << hOwner); 236 | 237 | hOwnerIn = NULL; 238 | OnCloseIn(); 239 | } 240 | 241 | myPTRACE(1, "T38Modem\t" << name << " OpenIn: open " << hOwner); 242 | 243 | hOwnerIn = hOwner; 244 | isFakeOwnerIn = fake; 245 | OnOpenIn(); 246 | } 247 | 248 | void EngineBase::OpenOut(HOWNEROUT hOwner, PBoolean fake) 249 | { 250 | PWaitAndSignal mutexWait(Mutex); 251 | 252 | while (hOwnerOut != NULL) { 253 | if (hOwnerOut == hOwner) { 254 | myPTRACE(1, "T38Modem\t" << name << " OpenOut: re-open " << hOwner); 255 | return; 256 | } 257 | 258 | if (fake) { 259 | myPTRACE(1, "T38Modem\t" << name << " OpenOut: disabled close " << hOwnerOut << " by fake " << hOwner); 260 | return; 261 | } 262 | 263 | myPTRACE(1, "T38Modem\t" << name << " OpenOut " << (isFakeOwnerOut ? ": close fake " : "WARNING: close ") << hOwnerOut << " by " << hOwner); 264 | 265 | hOwnerOut = NULL; 266 | OnCloseOut(); 267 | } 268 | 269 | myPTRACE(1, "T38Modem\t" << name << " OpenOut: open " << hOwner); 270 | 271 | hOwnerOut = hOwner; 272 | isFakeOwnerOut = fake; 273 | OnOpenOut(); 274 | } 275 | 276 | void EngineBase::OnOpenIn() 277 | { 278 | firstIn = TRUE; 279 | ModemCallbackWithUnlock(cbpUpdateState); 280 | } 281 | 282 | void EngineBase::OnOpenOut() 283 | { 284 | firstOut = TRUE; 285 | ModemCallbackWithUnlock(cbpUpdateState); 286 | } 287 | 288 | void EngineBase::CloseIn(HOWNERIN hOwner) 289 | { 290 | PWaitAndSignal mutexWait(Mutex); 291 | 292 | if (hOwnerIn == hOwner) { 293 | myPTRACE(1, "T38Modem\t" << name << " CloseIn: close " << (isFakeOwnerIn ? "fake " : "") << hOwner); 294 | 295 | if (!isFakeOwnerIn) 296 | isEnableFakeIn = FALSE; // allow re-enable fake stream 297 | 298 | hOwnerIn = NULL; 299 | OnCloseIn(); 300 | } else { 301 | myPTRACE(1, "T38Modem\t" << name << " CloseIn: re-close " << hOwner); 302 | } 303 | } 304 | 305 | void EngineBase::CloseOut(HOWNEROUT hOwner) 306 | { 307 | PWaitAndSignal mutexWait(Mutex); 308 | 309 | if (hOwnerOut == hOwner) { 310 | myPTRACE(1, "T38Modem\t" << name << " CloseOut: close " << (isFakeOwnerOut ? "fake " : "") << hOwner); 311 | 312 | if (!isFakeOwnerOut) 313 | isEnableFakeOut = FALSE; // allow re-enable fake stream 314 | 315 | hOwnerOut = NULL; 316 | OnCloseOut(); 317 | } else { 318 | myPTRACE(1, "T38Modem\t" << name << " CloseOut: re-close " << hOwner); 319 | } 320 | } 321 | 322 | void EngineBase::OnCloseIn() 323 | { 324 | ModemCallbackWithUnlock(cbpUpdateState); 325 | } 326 | 327 | void EngineBase::OnCloseOut() 328 | { 329 | ModemCallbackWithUnlock(cbpUpdateState); 330 | } 331 | 332 | void EngineBase::EnableFakeIn(PBoolean enable) 333 | { 334 | PWaitAndSignal mutexWait(Mutex); 335 | 336 | if (isEnableFakeIn == enable) 337 | return; 338 | 339 | myPTRACE(3, "T38Modem\t" << name << " EnableFakeIn: " << (enable ? "enable" : "disable")); 340 | 341 | isEnableFakeIn = enable; 342 | OnChangeEnableFakeIn(); 343 | } 344 | 345 | void EngineBase::OnChangeEnableFakeIn() 346 | { 347 | if (!isEnableFakeIn && hOwnerIn != NULL && isFakeOwnerIn) { 348 | myPTRACE(1, "T38Modem\t" << name << " OnChangeEnableFakeIn: close fake " << hOwnerIn); 349 | 350 | hOwnerIn = NULL; 351 | OnCloseIn(); 352 | } 353 | } 354 | 355 | void EngineBase::EnableFakeOut(PBoolean enable) 356 | { 357 | PWaitAndSignal mutexWait(Mutex); 358 | 359 | if (isEnableFakeOut == enable) 360 | return; 361 | 362 | myPTRACE(3, "T38Modem\t" << name << " EnableFakeOut: " << (enable ? "enable" : "disable")); 363 | 364 | isEnableFakeOut = enable; 365 | OnChangeEnableFakeOut(); 366 | } 367 | 368 | void EngineBase::OnChangeEnableFakeOut() 369 | { 370 | if (!isEnableFakeOut && hOwnerOut != NULL && isFakeOwnerOut) { 371 | myPTRACE(1, "T38Modem\t" << name << " OnChangeEnableFakeOut: close fake " << hOwnerOut); 372 | 373 | hOwnerOut = NULL; 374 | OnCloseOut(); 375 | } 376 | } 377 | 378 | void EngineBase::ChangeModemClass(ModemClass newModemClass) 379 | { 380 | PWaitAndSignal mutexWait(Mutex); 381 | 382 | if (modemClass == newModemClass) 383 | return; 384 | 385 | modemClass = newModemClass; 386 | 387 | myPTRACE(1, "T38Modem\t" << name << " ChangeModemClass to " << modemClass); 388 | 389 | OnChangeModemClass(); 390 | } 391 | 392 | void EngineBase::OnChangeModemClass() 393 | { 394 | if (recvUserInput) { 395 | delete recvUserInput; 396 | recvUserInput = NULL; 397 | } 398 | 399 | myPTRACE(1, "T38Modem\t" << name << " OnChangeModemClass to " << modemClass); 400 | } 401 | 402 | PBoolean EngineBase::TryLockModemCallback() 403 | { 404 | MutexModem.Wait(); 405 | 406 | if (!MutexModemCallback.Wait(0)) { 407 | MutexModem.Signal(); 408 | return FALSE; 409 | } 410 | 411 | return TRUE; 412 | } 413 | 414 | void EngineBase::UnlockModemCallback() 415 | { 416 | MutexModemCallback.Signal(); 417 | MutexModem.Signal(); 418 | } 419 | 420 | void EngineBase::ModemCallbackWithUnlock(INT extra) 421 | { 422 | Mutex.Signal(); 423 | MutexModemCallback.Wait(); 424 | 425 | if (!modemCallback.IsNULL()) 426 | modemCallback(*this, extra); 427 | 428 | MutexModemCallback.Signal(); 429 | Mutex.Wait(); 430 | } 431 | 432 | void EngineBase::WriteUserInput(const PString & value) 433 | { 434 | myPTRACE(1, "T38Modem\t" << name << " WriteUserInput " << value); 435 | 436 | PWaitAndSignal mutexWait(Mutex); 437 | 438 | OnUserInput(value); 439 | } 440 | 441 | void EngineBase::OnUserInput(const PString & value) 442 | { 443 | myPTRACE(4, "T38Modem\t" << name << " OnUserInput " << value); 444 | 445 | if (recvUserInput && !recvUserInput->isFull()) { 446 | recvUserInput->PutData((const char *)value, value.GetLength()); 447 | 448 | ModemCallbackWithUnlock(cbpUserInput); 449 | } 450 | } 451 | 452 | int EngineBase::RecvUserInput(void * pBuf, PINDEX count) 453 | { 454 | PWaitAndSignal mutexWaitModem(MutexModem); 455 | PWaitAndSignal mutexWait(Mutex); 456 | 457 | if (!recvUserInput) 458 | return -1; 459 | 460 | return recvUserInput->GetData(pBuf, count); 461 | } 462 | /////////////////////////////////////////////////////////////// 463 | 464 | -------------------------------------------------------------------------------- /opal/t38modem_2005.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 26 | 29 | 32 | 35 | 38 | 47 | 68 | 71 | 76 | 79 | 89 | 92 | 95 | 98 | 103 | 106 | 109 | 112 | 115 | 116 | 125 | 128 | 131 | 134 | 137 | 146 | 166 | 169 | 174 | 177 | 188 | 191 | 194 | 197 | 202 | 205 | 208 | 211 | 214 | 215 | 224 | 227 | 230 | 233 | 236 | 245 | 266 | 269 | 274 | 277 | 287 | 290 | 293 | 296 | 301 | 304 | 307 | 310 | 313 | 314 | 315 | 316 | 317 | 318 | 322 | 325 | 326 | 329 | 330 | 333 | 334 | 337 | 338 | 341 | 342 | 345 | 346 | 349 | 350 | 353 | 354 | 357 | 358 | 361 | 362 | 365 | 366 | 369 | 370 | 373 | 376 | 380 | 381 | 384 | 388 | 389 | 392 | 396 | 397 | 398 | 401 | 402 | 405 | 406 | 409 | 410 | 413 | 414 | 417 | 420 | 421 | 424 | 425 | 428 | 429 | 432 | 433 | 436 | 437 | 440 | 441 | 444 | 445 | 446 | 447 | 451 | 454 | 455 | 458 | 459 | 462 | 463 | 466 | 467 | 470 | 471 | 474 | 475 | 478 | 479 | 482 | 483 | 486 | 487 | 490 | 491 | 494 | 495 | 498 | 499 | 502 | 503 | 506 | 507 | 510 | 511 | 514 | 515 | 518 | 521 | 522 | 525 | 526 | 529 | 530 | 533 | 534 | 537 | 538 | 541 | 542 | 545 | 546 | 547 | 548 | 552 | 553 | 556 | 559 | 560 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | --------------------------------------------------------------------------------