Current status of the ppcgui branch
Athanasios Karapantelakis
athkar at kth.se
Mon Nov 13 15:53:31 CET 2006
Hello,
There have been some developments with the pocket pc version (namely
ppcgui branch), and trying to run minisip properly, initially as a
console application, using a third-party console emulator [1].
The first problem was that the text output on the console, namely the
char * return type widely use from error/debug reporting functions as
well as from textui itself, does not apply in Windows CE, which uses
UNICODE instead of ASCII [2]. In order to solve this problem, a new
universal library was created ("libmconsole"), which accepts a char*
input, and converts it accordingly to wchar_t, if the architecture is
windows ce, or simply outputs the char* text otherwise. Furthermore this
library has the option to send the output text encapsulated in UDP
packets, so debugging would be more convenient in the future GUI, where
no text output is available. Another thing observed is that of
overlapping text, when multiple threads tried to output something to the
console at the same time. Note that this was common both for the windows
version of minisip, and the pocket pc version. libmconsole encapsulates
the output function in a critical region, so that one thread can output
text each time. Attached is the wceconsole.cpp file featuring the
functionality mentioned above.
Another problem for Windows ce is that there is no windns library
available, so it is not possible to resolve the ip address of a domain
name (at least with the code we found on the trunk). The function
responsible for resolving domain names to ip addresses is called
getHostHandlingService, located in NetworkFunctions.cxx, and for windows
CE, it just returns the domain string, without doing any effort to
resolve it to an IP address. Naturally, this will work only if the
address of the registrar is an IP address and not a canonical name. If
there is any omission here, or this functionality is already implemented
elsewhere, feedback is most appreciated.
The problems the project faces at the moment concern thread
synchronization, and seem to be related to the function
WaitForSingleObject. As I understand it, this function is called
whenever the program waits for another thread to finish a task, and in
the meantime it goes into sleep mode, consuming a small amount of
resources (critical for this platform). However, if used with the
INFINITE handle (wait forever, without a timeout), the current thread
can wait forever, until another thread finishes its task, and this is
observed in the following cases (examples with partial call stacks):
When placing a call, at some point the program has to construct the
sip stack for an invite message:
Sip.cxx [minisip] ->
addDialog sipdialogcontainer.cxx [libmsip] ->
addDialog sipmessagedispatcher.cxx [libmsip] - dialogListLock.lock(); ->
Mutex::lock [libmutil] -
WaitForSingleObject(*((HANDLE*)handle_ptr),INFINITE);
When shutting down the programm, the sip stack thread must exit, but
it never does:
minisip.cxx "sip->join()" minisip::exit [minisip] ->
sip.cxx "thread->join() [minisip] ->
thread.cxx thread::join() [libmutil]
Upon removing the WaitForSingleObject from lock and join functions,
the program does not get stuck, but behaves erratically:
- When calling an INVITE goes out but a reply (e.g. OK or CANCEL) is not
sent back, when hanging up a CANCEL is sent, but still no reply is received.
- In the case of an incoming call the program informs the user of an
incoming call from a (properly resolved) SIP uri but it cannot
initialize the RTP stack.
This springs some suspicions about whether the thread model in
Windows behaves similarly in Windows CE (note that the same code
compiles & runs successfully on windows - using the visual studio
compiler), perhaps setting a timeout instead of INFINITE would help in
this case?
Since the project files and many source files changed in order to
support the new console library, uploading them using commit would again
result in a large email. Is there any way to do a copy with kdesvn ?
[1] http://www.symbolictools.de/public/pocketconsole/index.htm
[2] http://msdn2.microsoft.com/en-us/library/ms834193.aspx
-------------- next part --------------
#include "wceconsole.h"
#define IP_ADDR "130.237.15.248"
static CRITICAL_SECTION consoleMutex;
//void consoleOut (string inputString, CRITICAL_SECTION consoleOUT){
#ifdef LIBMCONSOLE_EXPORTS
LIBMCONSOLE_API void consoleOut (char* inputString){
#else
void consoleOut (char* inputString){
#endif
#ifdef _WIN32_WCE // UDP sent packet section
static int socketIsOpen = 0;
static SOCKET s;
static SOCKADDR_IN targetDevice;
EnterCriticalSection(&consoleMutex);
if (socketIsOpen == 0){
#ifdef _WIN32_WCE
InitializeCriticalSection(&consoleMutex); //put this where init. is done
#endif
socketIsOpen = 1;
s = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); //open socket
if (s == INVALID_SOCKET) {
int serror = WSAGetLastError();
wprintf(L"wceconsole: socket error :%d\n", serror);
}
memset (&targetDevice, 0, sizeof(SOCKADDR_IN));
targetDevice.sin_family = AF_INET;
targetDevice.sin_port = htons(60);
targetDevice.sin_addr.S_un.S_addr = inet_addr(IP_ADDR);
}
sendto(s, inputString, strlen(inputString), 0, (SOCKADDR *) &targetDevice, sizeof (SOCKADDR_IN));
#endif
const char *consoleOutTemp = inputString;
#ifdef _WCE_ARCH
wchar_t buffer [256];
mbstowcs(buffer, inputString, 256 );
wprintf(L"%s", buffer);
#elif defined _OTHER_ARCH
printf("%s", consoleOutTemp);
break;
#else // Shouln't go here, nevertheless the structure is maintained for future architectures
;
#endif
consoleOutTemp = NULL;
LeaveCriticalSection(&consoleMutex);
int i = 0;
for (i = 1000000; i > 0; i--);
}
void consoleOutCleanup(){
#ifdef _WIN32_WCE
DeleteCriticalSection(&consoleMutex); //do this in cleanup
#endif
// TODO: socket cleanup
}
More information about the Minisip-devel
mailing list