diff --git a/engine/DataFormat.cpp b/engine/DataFormat.cpp index 12c3d6ef..d7b3546f 100644 --- a/engine/DataFormat.cpp +++ b/engine/DataFormat.cpp @@ -47,7 +47,7 @@ private: class SimpleTranslator : public DataTranslator { public: - SimpleTranslator(const String& sFormat, const String& dFormat) + SimpleTranslator(const DataFormat& sFormat, const DataFormat& dFormat) : DataTranslator(sFormat,dFormat) { } virtual void Consume(const DataBlock& data, unsigned long timeDelta) { @@ -102,7 +102,8 @@ static const FormatInfo s_formats[] = { }; static flist* s_flist = 0; -static const FormatInfo* s_slin = &s_formats[0]; +static const FormatInfo* f_slin = &s_formats[0]; +static const char s_slin[] = "slin"; const FormatInfo* FormatRepository::getFormat(const String& name) { @@ -149,11 +150,24 @@ const FormatInfo* FormatRepository::addFormat(const String& name, int drate, int return f; } +void DataFormat::changed() +{ + m_parsed = 0; + String::changed(); +} + +const FormatInfo* DataFormat::getInfo() const +{ + if (!(m_parsed || null())) + m_parsed = FormatRepository::getFormat(*this); + return m_parsed; +} + void DataSource::Forward(const DataBlock& data, unsigned long timeDelta) { // no number of samples provided - try to guess if (!timeDelta) { - const FormatInfo* f = FormatRepository::getFormat(m_format); + const FormatInfo* f = m_format.getInfo(); if (f) timeDelta = f->guessSamples(data.length()); } @@ -409,7 +423,7 @@ void DataTranslator::uninstall(TranslatorFactory* factory) s_mutex.unlock(); } -String DataTranslator::srcFormats(const String& dFormat) +String DataTranslator::srcFormats(const DataFormat& dFormat) { String s; s_mutex.lock(); @@ -429,7 +443,7 @@ String DataTranslator::srcFormats(const String& dFormat) return s; } -String DataTranslator::destFormats(const String& sFormat) +String DataTranslator::destFormats(const DataFormat& sFormat) { String s; s_mutex.lock(); @@ -449,7 +463,7 @@ String DataTranslator::destFormats(const String& sFormat) return s; } -int DataTranslator::cost(const String& sFormat, const String& dFormat) +int DataTranslator::cost(const DataFormat& sFormat, const DataFormat& dFormat) { int c = -1; s_mutex.lock(); @@ -468,7 +482,7 @@ int DataTranslator::cost(const String& sFormat, const String& dFormat) return c; } -DataTranslator* DataTranslator::create(const String& sFormat, const String& dFormat) +DataTranslator* DataTranslator::create(const DataFormat& sFormat, const DataFormat& dFormat) { if (sFormat == dFormat) { Debug(DebugInfo,"Not creating identity DataTranslator for \"%s\"",sFormat.c_str()); @@ -541,7 +555,7 @@ bool DataTranslator::attachChain(DataSource* source, DataConsumer* consumer) } } NDebug(retv ? DebugAll : DebugWarn,"DataTranslator::attachChain [%p] \"%s\" -> [%p] \"%s\" %s", - source,source->getFormatName(),consumer,consumer->getFormatName(), + source,source->getFormat(),consumer,consumer->getFormat(), retv ? "succeeded" : "failed"); return retv; } diff --git a/engine/Socket.cpp b/engine/Socket.cpp index a4468c84..bb6bdcd0 100644 --- a/engine/Socket.cpp +++ b/engine/Socket.cpp @@ -22,19 +22,6 @@ #include "yateclass.h" -#ifndef _WINDOWS -#ifndef SOCKET -typedef int SOCKET; -#endif -#endif - -#ifndef IPTOS_LOWDELAY -#define IPTOS_LOWDELAY 0x10 -#define IPTOS_THROUGHPUT 0x08 -#define IPTOS_RELIABILITY 0x04 -#define IPTOS_MINCOST 0x02 -#endif - using namespace TelEngine; Socket::Socket() @@ -140,47 +127,24 @@ bool Socket::listen(unsigned int backlog) return checkError(::listen(m_handle,backlog)); } -bool Socket::setOption(int level, int name, const void* value, int length) +bool Socket::setOption(int level, int name, const void* value, socklen_t length) { if (!value) length = 0; return checkError(::setsockopt(m_handle,level,name,(const char*)value,length)); } -bool Socket::getOption(int level, int name, void* buffer, int* length) +bool Socket::getOption(int level, int name, void* buffer, socklen_t* length) { -#ifdef _WINDOWS + if (length && !buffer) + *length = 0; return checkError(::getsockopt(m_handle,level,name,(char*)buffer,length)); -#else - socklen_t len = 0; - if (length) - len = *length; - bool ok = checkError(::getsockopt(m_handle,level,name,(char*)buffer,&len)); - if (length) - *length = len; - return ok; -#endif } -bool Socket::setTOS(TOS tos) +bool Socket::setTOS(int tos) { #ifdef IP_TOS - int val = tos; - switch (tos) { - case LowDelay: - val = IPTOS_LOWDELAY; - break; - case MaxThroughput: - val = IPTOS_THROUGHPUT; - break; - case MaxReliability: - val = IPTOS_RELIABILITY; - break; - case MinCost: - val = IPTOS_MINCOST; - break; - } - return setOption(IPPROTO_IP,IP_TOS,&val,sizeof(val)); + return setOption(IPPROTO_IP,IP_TOS,&tos,sizeof(tos)); #else m_error = ENOTIMPL; return false; diff --git a/engine/Thread.cpp b/engine/Thread.cpp index 74679331..d3240cfc 100644 --- a/engine/Thread.cpp +++ b/engine/Thread.cpp @@ -179,9 +179,7 @@ void ThreadPrivate::run() Thread::usleep(10); m_thread->run(); -#ifdef _WINDOWS - destroy(); -#else +#ifndef _WINDOWS pthread_cleanup_pop(1); #endif } @@ -324,7 +322,7 @@ void* ThreadPrivate::startFunc(void* arg) ThreadPrivate *t = reinterpret_cast(arg); t->run(); #ifdef _WINDOWS - t->cleanup(); + t->destroy(); #else return 0; #endif diff --git a/modules/iaxchan.cpp b/modules/iaxchan.cpp index b88f40b8..71355ff5 100644 --- a/modules/iaxchan.cpp +++ b/modules/iaxchan.cpp @@ -108,13 +108,7 @@ public: void answer(iax_event *e); void reg(iax_event *e); void run(void); - IAXConnection *find(iax_session *session); void handleEvent(iax_event *event); - - inline ObjList &calls() - { return m_calls; } -private: - ObjList m_calls; }; class IAXConnection : public Channel @@ -160,6 +154,7 @@ public: virtual ~IAXPlugin(); virtual void initialize(); virtual bool msgExecute(Message& msg, String& dest); + IAXConnection *find(iax_session *session); IAXEndPoint *m_endpoint; }; @@ -294,7 +289,7 @@ void IAXEndPoint::run(void) case IAX_EVENT_TIMEOUT: case IAX_EVENT_REJECT: case IAX_EVENT_HANGUP: - if ((conn = find(e->session)) != 0) { + if ((conn = iplugin.find(e->session)) != 0) { conn->abort(e->etype); conn->destruct(); } @@ -483,17 +478,6 @@ void IAXEndPoint::reg(iax_event *e) s_mutex.unlock(); } -IAXConnection* IAXEndPoint::find(iax_session *session) -{ - ObjList *p = m_calls.skipNull(); - for (; p; p=p->skipNext()) { - IAXConnection *t = static_cast(p->get()); - if (t->session() == session) - return t; - } - return 0; -} - IAXConnection::IAXConnection(Driver* driver, const char* addr, iax_session *session) : Channel(driver,0,(session == 0)), m_session(session), m_final(false), m_muted(false), @@ -653,7 +637,7 @@ void IAXConnection::hangup(const char *reason) if (!reason) reason = m_reason; if (!reason) - reason = "Unexpected problem"; + reason = Engine::exiting() ? "Server shutdown" : "Unexpected problem"; if (!m_final) { s_mutex.lock(); m_final = true; @@ -894,6 +878,17 @@ bool IAXPlugin::msgExecute(Message& msg, String& dest) return true; }; +IAXConnection* IAXPlugin::find(iax_session *session) +{ + ObjList *p = channels().skipNull(); + for (; p; p=p->skipNext()) { + IAXConnection *t = static_cast(p->get()); + if (t->session() == session) + return t; + } + return 0; +} + IAXPlugin::IAXPlugin() : Driver("iax","varchans"), m_endpoint(0) { diff --git a/modules/rmanager.cpp b/modules/rmanager.cpp index 6a078e3b..4dea32d0 100644 --- a/modules/rmanager.cpp +++ b/modules/rmanager.cpp @@ -150,10 +150,12 @@ Connection::~Connection() void Connection::run() { +#ifdef O_NONBLOCK if (::fcntl(m_socket,F_SETFL,O_NONBLOCK)) { Debug("RManager",DebugGoOn, "Failed to set tcp socket to nonblocking mode: %s\n", strerror(errno)); return; } +#endif // For the sake of responsiveness try to turn off the tcp assembly timer int arg = 1; if (::setsockopt(m_socket, SOL_SOCKET, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0) @@ -178,6 +180,8 @@ void Connection::run() Debug("RManager",DebugInfo,"Socket exception condition on %d",m_socket); return; } + if (!FD_ISSET(m_socket,&readfd)) + continue; int readsize = ::read(m_socket,buffer+posinbuf,sizeof(buffer)-posinbuf-1); if (!readsize) { Debug("RManager",DebugInfo,"Socket condition EOF on %d",m_socket); diff --git a/windows/_rmanager.dsp b/windows/_rmanager.dsp index ec9e65e0..655aabd8 100644 --- a/windows/_rmanager.dsp +++ b/windows/_rmanager.dsp @@ -54,7 +54,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 -# ADD LINK32 kernel32.lib /nologo /dll /machine:I386 /out:"Release/rmanager.yate" +# ADD LINK32 kernel32.lib ws2_32.lib /nologo /dll /machine:I386 /out:"Release/rmanager.yate" # SUBTRACT LINK32 /incremental:yes !ELSEIF "$(CFG)" == "_rmanager - Win32 Debug" @@ -82,7 +82,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib /nologo /dll /incremental:no /debug /machine:I386 /out:"Debug/rmanager.yate" /pdbtype:sept +# ADD LINK32 kernel32.lib ws2_32.lib /nologo /dll /incremental:no /debug /machine:I386 /out:"Debug/rmanager.yate" /pdbtype:sept !ENDIF diff --git a/yateclass.h b/yateclass.h index 62d73cbf..5b39df5a 100644 --- a/yateclass.h +++ b/yateclass.h @@ -55,6 +55,8 @@ typedef signed __int64 int64_t; typedef unsigned __int64 u_int64_t; typedef unsigned __int64 uint64_t; +typedef int socklen_t; + #define vsnprintf _vsnprintf #define snprintf _snprintf #define strcasecmp _stricmp @@ -99,7 +101,9 @@ typedef unsigned __int64 uint64_t; #include #include +#ifndef SOCKET typedef int SOCKET; +#endif #define YATE_API @@ -107,6 +111,13 @@ typedef int SOCKET; #endif /* ! _WINDOWS */ +#ifndef IPTOS_LOWDELAY +#define IPTOS_LOWDELAY 0x10 +#define IPTOS_THROUGHPUT 0x08 +#define IPTOS_RELIABILITY 0x04 +#define IPTOS_MINCOST 0x02 +#endif + struct timeval; /** @@ -2177,10 +2188,10 @@ public: * Types of service */ enum TOS { - LowDelay = 0x1000, - MaxThroughput, - MaxReliability, - MinCost, + LowDelay = IPTOS_LOWDELAY, + MaxThroughput = IPTOS_THROUGHPUT, + MaxReliability = IPTOS_RELIABILITY, + MinCost = IPTOS_MINCOST, }; /** @@ -2262,7 +2273,7 @@ public: * @param length Size of the supplied buffer * @return True if operation was successfull, false if an error occured */ - bool setOption(int level, int name, const void* value = 0, int length = 0); + bool setOption(int level, int name, const void* value = 0, socklen_t length = 0); /** * Get socket options @@ -2271,14 +2282,14 @@ public: * @param length Pointer to size of the supplied buffer, will be filled on return * @return True if operation was successfull, false if an error occured */ - bool getOption(int level, int name, void* buffer, int* length); + bool getOption(int level, int name, void* buffer, socklen_t* length); /** * Set the Type of Service on the IP level of this socket - * @param tos New TOS enum to set or byte value + * @param tos New TOS bits to set * @return True if operation was successfull, false if an error occured */ - bool setTOS(TOS tos); + bool setTOS(int tos); /** * Start listening for incoming connections on the socket diff --git a/yatephone.h b/yatephone.h index 4dcee643..8f98e722 100644 --- a/yatephone.h +++ b/yatephone.h @@ -164,6 +164,73 @@ public: static const FormatInfo* addFormat(const String& name, int drate, int fsize, const String& type = "audio", int srate = 8000, int nchan = 1); }; +/** + * An extension of a String that can parse data formats + * @short A Data format + */ +class YATE_API DataFormat : public String +{ +public: + /** + * Creates a new, empty string. + */ + inline DataFormat() + : m_parsed(0) + { } + + /** + * Creates a new initialized format. + * @param value Initial value of the format + */ + inline DataFormat(const char* value) + : String(value), m_parsed(0) + { } + + /** + * Copy constructor. + * @param value Initial value of the format + */ + DataFormat(const DataFormat& value) + : String(value), m_parsed(0) + { } + + /** + * Constructor from String reference + * @param value Initial value of the format + */ + DataFormat(const String& value) + : String(value), m_parsed(0) + { } + + /** + * Constructor from String pointer. + * @param value Initial value of the format + */ + DataFormat(const String* value) + : String(value), m_parsed(0) + { } + + /** + * Assignment operator. + */ + inline DataFormat& operator=(const DataFormat& value) + { String::operator=(value); return *this; } + + /** + * Retrive a pointer to the format information + * @return Pointer to the associated format info or NULL if error + */ + const FormatInfo* getInfo() const; + +protected: + /** + * Called whenever the value changed (except in constructors). + */ + virtual void changed(); + + mutable const FormatInfo* m_parsed; +}; + /** * A generic data handling object */ @@ -174,54 +241,33 @@ public: * Construct a DataNode * @param format Description of the data format, default none */ - inline DataNode(const FormatInfo* format = 0) - : m_format(format), m_timestamp(0) { } - - /** - * Construct a DataNode from a format name - * @param format Name of the data format, default none - */ - inline DataNode(const String& format) - : m_format(FormatRepository::getFormat(format)), m_timestamp(0) { } + inline DataNode(const char* format = 0) + : m_format(format), m_timestamp(0) + { } /** * Get the computing cost of converting the data to the format asked * @param format Name of the format to check for * @return -1 if unsupported, 0 for native format else cost in KIPS */ - virtual int costFormat(const FormatInfo* format) + virtual int costFormat(const DataFormat& format) { return -1; } - /** - * Change the format used to transfer data - * @param format Description of the format to set for data - * @return True if the format changed successfully, false if not changed - */ - virtual bool setFormat(const FormatInfo* format = 0) - { return false; } - /** * Change the format used to transfer data * @param format Name of the format to set for data * @return True if the format changed successfully, false if not changed */ - inline bool setFormat(const String& format) - { return setFormat(FormatRepository::getFormat(format)); } + virtual bool setFormat(const DataFormat& format) + { return false; } /** * Get the description of the format currently in use * @return Pointer to the data format */ - inline const FormatInfo* getFormat() const + inline const DataFormat& getFormat() const { return m_format; } - /** - * Get the name of the format currently in use - * @return Name of the data format - */ - inline const char* getFormatName() const - { return m_format ? m_format->name : 0; } - /** * Get the current position in the data stream * @return Timestamp of current data position @@ -230,23 +276,7 @@ public: { return m_timestamp; } protected: - /** - * Change the format used to transfer data - * @param format Description of the format to set for data - * @return True if the format changed successfully, false if not changed - */ - inline void setFormatInternal(const FormatInfo* format = 0) - { m_format = format; } - - /** - * Change the format used to transfer data - * @param format Name of the format to set for data - * @return True if the format changed successfully, false if not changed - */ - inline void setFormatInternal(const String& format) - { setFormatInternal(FormatRepository::getFormat(format)); } - - const FormatInfo* m_format; + DataFormat m_format; unsigned long m_timestamp; }; @@ -256,19 +286,13 @@ protected: class YATE_API DataConsumer : public DataNode { friend class DataSource; -public: - /** - * Consumer constructor - * @param format Description of the data format - */ - inline DataConsumer(const FormatInfo *format) - : DataNode(format), m_source(0) { } +public: /** * Consumer constructor * @param format Name of the data format, default "slin" (Signed Linear) */ - inline DataConsumer(const String& format = "slin") + inline DataConsumer(const char* format = "slin") : DataNode(format), m_source(0) { } /** @@ -304,19 +328,13 @@ private: class YATE_API DataSource : public DataNode { friend class DataTranslator; -public: - /** - * Source constructor - * @param format Description of the data format - */ - inline DataSource(const FormatInfo* format) - : DataNode(format), m_translator(0) { } +public: /** * Source constructor * @param format Name of the data format, default "slin" (Signed Linear) */ - inline DataSource(const String& format = "slin") + inline DataSource(const char* format = "slin") : DataNode(format), m_translator(0) { } /** @@ -399,18 +417,11 @@ public: Thread* thread() const; protected: - /** - * Threaded Source constructor - * @param format Description of the data format - */ - inline ThreadedSource(const FormatInfo* format) - : DataSource(format), m_thread(0) { } - /** * Threaded Source constructor * @param format Name of the data format, default "slin" (Signed Linear) */ - inline ThreadedSource(const String& format = "slin") + inline ThreadedSource(const char* format = "slin") : DataSource(format), m_thread(0) { } /** @@ -468,14 +479,14 @@ public: * @param dFormat Name of destination format * @return Space separated list of source formats */ - static String srcFormats(const String& dFormat = "slin"); + static String srcFormats(const DataFormat& dFormat = "slin"); /** * Get a textual list of formats supported for a given input format * @param sFormat Name of source format * @return Space separated list of destination formats */ - static String destFormats(const String& sFormat = "slin"); + static String destFormats(const DataFormat& sFormat = "slin"); /** * Finds the cost of a translator given the source and destination format names @@ -483,7 +494,7 @@ public: * @param dFormat Name of the destination format (data supplied to the source) * @return Cost of best (cheapest) codec or -1 if no known codec exists */ - static int cost(const String& sFormat, const String& dFormat); + static int cost(const DataFormat& sFormat, const DataFormat& dFormat); /** * Creates a translator given the source and destination format names @@ -491,7 +502,7 @@ public: * @param dFormat Name of the destination format (data supplied to the source) * @return A pointer to a DataTranslator object or NULL if no known codec exists */ - static DataTranslator* create(const String& sFormat, const String& dFormat); + static DataTranslator* create(const DataFormat& sFormat, const DataFormat& dFormat); /** * Attach a consumer to a source, possibly trough a chain of translators @@ -549,7 +560,7 @@ public: * @param dFormat Name of the destination format (data supplied to the source) * @return A pointer to a DataTranslator object or NULL */ - virtual DataTranslator* create(const String& sFormat, const String& dFormat) = 0; + virtual DataTranslator* create(const DataFormat& sFormat, const DataFormat& dFormat) = 0; /** * Get the capabilities table of this translator