From 196824372226561334cd638d6471267cbffb354c Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Thu, 17 May 2007 14:09:35 +0000 Subject: [PATCH] Porting Toolkit to Symbian. It should work while some sporadic odd crashes remain. However I was able to run mybot on SILCNet. Basically tested scheduler, net routines, socket routines, threads and some other utility routines. --- README.SYMBIAN | 2 +- lib/silcutil/silcschedule.c | 18 +- lib/silcutil/silcschedule.h | 16 +- lib/silcutil/silcsocketstream.c | 1 + lib/silcutil/silcthread.h | 4 + lib/silcutil/symbian/silcsymbiannet.cpp | 118 +++-- lib/silcutil/symbian/silcsymbianscheduler.cpp | 409 +++++++++++++----- .../symbian/silcsymbiansocketstream.cpp | 10 +- lib/silcutil/symbian/silcsymbianthread.cpp | 60 ++- lib/silcutil/symbian/silcsymbianutil.cpp | 13 +- symbian/silcdefs.h | 2 +- 11 files changed, 459 insertions(+), 194 deletions(-) diff --git a/README.SYMBIAN b/README.SYMBIAN index 84fe4dc9..f37cf939 100644 --- a/README.SYMBIAN +++ b/README.SYMBIAN @@ -46,7 +46,7 @@ Building with Carbide.c++ After starting the Carbide.c++ you will need to import the SILC Toolkit project. Go to File -> Import -> Symbian OS -> Symbian OS Bld.inf file, -and go to the extracted SILC Toolkit source tree and find symbian/bld.inf +and go to the extracted SILC Toolkit source tree and find symbian\bld.inf file and import it. When Carbide.c++ asks for the Root Directory, select the root of the extracted SILC Toolkit source tree, if not already selected. diff --git a/lib/silcutil/silcschedule.c b/lib/silcutil/silcschedule.c index 3853a1bb..6d3f09e1 100644 --- a/lib/silcutil/silcschedule.c +++ b/lib/silcutil/silcschedule.c @@ -476,9 +476,12 @@ static SilcBool silc_schedule_iterate(SilcSchedule schedule, int timeout_usecs) continue; } else { - /* Error */ - if (silc_likely(errno == EINTR)) + /* Error or special case handling */ + if (errno == EINTR) continue; + if (ret == -2) + break; + SILC_LOG_ERROR(("Error in select()/poll(): %s", strerror(errno))); continue; } @@ -501,6 +504,7 @@ SilcBool silc_schedule_one(SilcSchedule schedule, int timeout_usecs) /* Runs the scheduler and blocks here. When this returns the scheduler has ended. */ +#ifndef SILC_SYMBIAN void silc_schedule(SilcSchedule schedule) { SILC_LOG_DEBUG(("Running scheduler")); @@ -510,6 +514,7 @@ void silc_schedule(SilcSchedule schedule) silc_schedule_iterate(schedule, -1); SILC_SCHEDULE_UNLOCK(schedule); } +#endif /* !SILC_SYMBIAN */ /* Wakes up the scheduler. This is used only in multi-threaded environments where threads may add new tasks or remove old tasks @@ -664,6 +669,15 @@ SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd, out: SILC_SCHEDULE_UNLOCK(schedule); + +#ifdef SILC_SYMBIAN + /* On symbian we wakeup scheduler immediately after adding timeout task + in case the task is added outside the scheduler loop (in some active + object). */ + if (task && task->type == 1) + silc_schedule_wakeup(schedule); +#endif /* SILC_SYMBIAN */ + return task; } diff --git a/lib/silcutil/silcschedule.h b/lib/silcutil/silcschedule.h index cfcdffbc..e92bb830 100644 --- a/lib/silcutil/silcschedule.h +++ b/lib/silcutil/silcschedule.h @@ -263,18 +263,18 @@ void silc_schedule_stop(SilcSchedule schedule); * * DESCRIPTION * - * The SILC scheduler. The program will run inside this function. - * When this returns the program is to be ended. Before this function can - * be called, one must call silc_schedule_init function. + * The SILC scheduler. The program will run inside this function. + * When this returns the program is to be ended. Before this function + * can be called, one must call silc_schedule_init function. * * NOTES * - * On Windows this will block the program, but will continue dispatching - * window messages, and thus can be used as the main loop of the program. + * On Windows this will block the calling thread but will continue + * to dispatch window messages, and thus can be used as the main loop + * of the program. * - * On Symbian this will return immediately. On Symbian calling - * silc_schedule is same as calling silc_schedule_one. This also means - * the caller must be already running Symbian Active Scheduler. + * On Symbian this will block the calling thread. The Symbian Active + * Scheduler must be running before calling this function. * ***/ void silc_schedule(SilcSchedule schedule); diff --git a/lib/silcutil/silcsocketstream.c b/lib/silcutil/silcsocketstream.c index 3140b6d9..e4b59f5a 100644 --- a/lib/silcutil/silcsocketstream.c +++ b/lib/silcutil/silcsocketstream.c @@ -171,6 +171,7 @@ silc_socket_tcp_stream_create(SilcSocket sock, SilcBool lookup, stream->ops = &silc_socket_stream_ops; stream->sock = sock; stream->schedule = schedule; + stream->connected = TRUE; l = silc_calloc(1, sizeof(*l)); if (!l) { diff --git a/lib/silcutil/silcthread.h b/lib/silcutil/silcthread.h index c6429a9b..3a4036f6 100644 --- a/lib/silcutil/silcthread.h +++ b/lib/silcutil/silcthread.h @@ -92,6 +92,10 @@ typedef void *(*SilcThreadStart)(void *context); * If the `waitable' is TRUE then another thread must always issue * silc_thread_wait to avoid memory leaks. * + * On Symbian Cleanup Stack is created and new Active Scheduler is + * installed automatically for the created thread. The thread also + * shares heap with the calling thread. + * ***/ SilcThread silc_thread_create(SilcThreadStart start_func, void *context, SilcBool waitable); diff --git a/lib/silcutil/symbian/silcsymbiannet.cpp b/lib/silcutil/symbian/silcsymbiannet.cpp index f297b628..25e7ad2f 100644 --- a/lib/silcutil/symbian/silcsymbiannet.cpp +++ b/lib/silcutil/symbian/silcsymbiannet.cpp @@ -20,6 +20,46 @@ #include "silc.h" #include "silcsymbiansocketstream.h" +/************************ Static utility functions **************************/ + +static SilcBool silc_net_set_sockaddr(TInetAddr *addr, const char *ip_addr, + int port) +{ + /* Check for IPv4 and IPv6 addresses */ + if (ip_addr) { + if (!silc_net_is_ip(ip_addr)) { + SILC_LOG_ERROR(("%s is not IP address", ip_addr)); + return FALSE; + } + + if (silc_net_is_ip4(ip_addr)) { + /* IPv4 address */ + unsigned char buf[4]; + TUint32 a; + + if (!silc_net_addr2bin(ip_addr, buf, sizeof(buf))) + return FALSE; + + SILC_GET32_MSB(a, buf); + addr->SetAddress(a); + addr->SetPort(port); + } else { +#ifdef HAVE_IPV6 + SILC_LOG_ERROR(("IPv6 not supported")); + return FALSE; +#else + SILC_LOG_ERROR(("Operating System does not support IPv6")); + return FALSE; +#endif + } + } else { + addr->SetAddress(0); + addr->SetPort(port); + } + + return TRUE; +} + /****************************** TCP Listener ********************************/ class SilcSymbianTCPListener; @@ -133,7 +173,6 @@ silc_net_tcp_create_listener(const char **local_ip_addr, SilcSymbianTCPListener *l = NULL; TInetAddr server; TInt ret; - TBuf<64> tmp; int i; SILC_LOG_DEBUG(("Creating TCP listener")); @@ -183,16 +222,14 @@ silc_net_tcp_create_listener(const char **local_ip_addr, if (ret != KErrNone) goto err; +#ifdef SILC_THREADS + /* Make our socket shareable between threads */ + l->ss.ShareAuto(); +#endif /* SILC_THREADS */ + /* Set listener address */ - if (local_ip_addr) { - server = TInetAddr(port); - tmp = (TText *)local_ip_addr[i]; - ret = server.Input(tmp); - if (ret != KErrNone) - goto err; - } else { - server = TInetAddr(KInetAddrAny, port); - } + if (!silc_net_set_sockaddr(&server, local_ip_addr[i], port)) + goto err; /* Create the socket */ ret = l->sock.Open(l->ss, KAfInet, KSockStream, KProtocolInetTcp); @@ -327,6 +364,8 @@ public: (SilcSocket)silc_create_symbian_socket(sock, ss), TRUE, FALSE, schedule, silc_net_connect_stream, (void *)this); + sock = NULL; + ss = NULL; } else { sock->Close(); delete sock; @@ -419,7 +458,6 @@ SilcAsyncOperation silc_net_tcp_connect(const char *local_ip_addr, SilcSymbianTCPConnect *conn; TInetAddr local, remote; SilcNetStatus status; - TBuf<64> tmp; TInt ret; if (!remote_ip_addr || remote_port < 1 || !schedule || !callback) @@ -460,10 +498,16 @@ SilcAsyncOperation silc_net_tcp_connect(const char *local_ip_addr, /* Connect to socket server */ ret = conn->ss->Connect(); if (ret != KErrNone) { + SILC_LOG_ERROR(("Error connecting to socket server, error %d", ret)); status = SILC_NET_ERROR; goto err; } +#ifdef SILC_THREADS + /* Make our socket shareable between threads */ + conn->ss->ShareAuto(); +#endif /* SILC_THREADS */ + /* Start async operation */ conn->op = silc_async_alloc(silc_net_connect_abort, NULL, (void *)conn); if (!conn->op) { @@ -493,20 +537,13 @@ SilcAsyncOperation silc_net_tcp_connect(const char *local_ip_addr, conn->sock->SetOpt(KSoTcpKeepAlive, KSolInetTcp, 1); /* Bind to the local address if provided */ - if (local_ip_addr) { - local = TInetAddr(0); - tmp = (TText *)local_ip_addr; - ret = local.Input(tmp); - if (ret == KErrNone) - ret = conn->sock->Bind(local); - } + if (local_ip_addr) + if (silc_net_set_sockaddr(&local, local_ip_addr, 0)) + conn->sock->Bind(local); /* Connect to the host */ - remote = TInetAddr(remote_port); - tmp = (TText *)conn->remote_ip; - ret = remote.Input(tmp); - if (ret != KErrNone) { - SILC_LOG_ERROR(("Cannot connect (cannot set address), error %d", ret)); + if (!silc_net_set_sockaddr(&remote, conn->remote_ip, remote_port)) { + SILC_LOG_ERROR(("Cannot connect (cannot set address)")); status = SILC_NET_ERROR; goto err; } @@ -546,7 +583,6 @@ SilcStream silc_net_udp_connect(const char *local_ip_addr, int local_port, TRequestStatus status; RSocket *sock = NULL; RSocketServ *ss = NULL; - TBuf<64> tmp; TInt ret; SILC_LOG_DEBUG(("Creating UDP stream")); @@ -570,16 +606,14 @@ SilcStream silc_net_udp_connect(const char *local_ip_addr, int local_port, if (ret != KErrNone) goto err; +#ifdef SILC_THREADS + /* Make our socket shareable between threads */ + ss->ShareAuto(); +#endif /* SILC_THREADS */ + /* Get local bind address */ - if (local_ip_addr) { - local = TInetAddr(local_port); - tmp = (TText *)local_ip_addr; - ret = local.Input(tmp); - if (ret != KErrNone) - goto err; - } else { - local = TInetAddr(KInetAddrAny, local_port); - } + if (!silc_net_set_sockaddr(&local, local_ip_addr, local_port)) + goto err; /* Create the socket */ ret = sock->Open(*ss, KAfInet, KSockDatagram, KProtocolInetUdp); @@ -600,16 +634,12 @@ SilcStream silc_net_udp_connect(const char *local_ip_addr, int local_port, /* Set to connected state if remote address is provided. */ if (remote_ip_addr && remote_port) { - remote = TInetAddr(remote_port); - tmp = (TText *)remote_ip_addr; - ret = remote.Input(tmp); - if (ret != KErrNone) - goto err; - - sock->Connect(remote, status); - if (status != KErrNone) { - SILC_LOG_DEBUG(("Cannot connect UDP stream")); - goto err; + if (silc_net_set_sockaddr(&remote, remote_ip_addr, remote_port)) { + sock->Connect(remote, status); + if (status != KErrNone) { + SILC_LOG_DEBUG(("Cannot connect UDP stream")); + goto err; + } } } @@ -769,4 +799,4 @@ SilcUInt16 silc_net_get_local_port(SilcSocket sock) return (SilcUInt16)addr.Port(); } -} /* extern "C" */ \ No newline at end of file +} /* extern "C" */ diff --git a/lib/silcutil/symbian/silcsymbianscheduler.cpp b/lib/silcutil/symbian/silcsymbianscheduler.cpp index f6f42cdc..fd131024 100644 --- a/lib/silcutil/symbian/silcsymbianscheduler.cpp +++ b/lib/silcutil/symbian/silcsymbianscheduler.cpp @@ -1,113 +1,296 @@ -/* - - silcsymbianschduler.cpp - - Author: Pekka Riikonen - - Copyright (C) 1998 - 2007 Pekka Riikonen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - -*/ - -/* On symbian the SILC Scheduler doesn't do anything. All timeout tasks - are dispatched by the generic scheduler implementation. Sockets and - file descriptors are dispatched automatically in their class - implementation, so adding FD Tasks on Symbian doesn't do anything. - - This also means that on Symbian the SILC Scheduler always returns - immediately. Because FD tasks use the Symbian scheduler the performance - is as good as it can be. For timeout tasks the performance is not an - issue. */ - -#include "silc.h" - -extern "C" { - -int silc_poll(SilcSchedule schedule, void *context) -{ - /* Return immediately, timeout. */ - return 0; -} - -SilcBool silc_schedule_internal_schedule_fd(SilcSchedule schedule, - void *context, - SilcTaskFd task, - SilcTaskEvent event_mask) -{ - /* Nothing to do */ - return TRUE; -} - -void *silc_schedule_internal_init(SilcSchedule schedule, - void *app_context) -{ - /* Nothing to do */ - return (void *)1; -} - - -void silc_schedule_internal_uninit(SilcSchedule schedule, void *context) -{ - /* Nothing to do */ -} - -void silc_schedule_internal_wakeup(SilcSchedule schedule, void *context) -{ - /* Nothing to do */ -} - -void silc_schedule_internal_signal_register(SilcSchedule schedule, - void *context, - SilcUInt32 sig, - SilcTaskCallback callback, - void *callback_context) -{ - /* Nothing to do */ -} - -void silc_schedule_internal_signal_unregister(SilcSchedule schedule, - void *context, - SilcUInt32 sig) -{ - /* Nothing to do */ -} - -void silc_schedule_internal_signals_call(SilcSchedule schedule, void *context) -{ - /* Nothing to do */ -} - -void silc_schedule_internal_signals_block(SilcSchedule schedule, void *context) -{ - /* Nothing to do */ -} - -void silc_schedule_internal_signals_unblock(SilcSchedule schedule, - void *context) -{ - /* Nothing to do */ -} - -EXPORT_C const SilcScheduleOps schedule_ops = -{ - silc_schedule_internal_init, - silc_schedule_internal_uninit, - silc_poll, - silc_schedule_internal_schedule_fd, - silc_schedule_internal_wakeup, - silc_schedule_internal_signal_register, - silc_schedule_internal_signal_unregister, - silc_schedule_internal_signals_call, - silc_schedule_internal_signals_block, - silc_schedule_internal_signals_unblock, -}; - -} /* extern "C" */ \ No newline at end of file +/* + + silcsymbianscheduler.cpp + + Author: Pekka Riikonen + + Copyright (C) 2007 Pekka Riikonen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + +*/ + +#include "silc.h" +#include + +/* The SILC Scheduler for Symbian handles only timeout tasks. Fd tasks are + not handled by the SILC Scheduler at all but are handled by the Symbian's + Active Scheduler. Fd and socket stream callbacks are delivered back + to caller in their respective class implementatios. + + The SILC Scheduler in Symbian works by creating CActiveSchedulerWait + when silc_schedule() is called. This will block the calling thread just + like silc_schedule is supposed to do. Under that Active Scheduler we + run our SilcSymbianScheduler timer which will handle the actual SILC + Scheduler by calling silc_schedule_one at correct times. The timeout + values are selected by the SILC Scheduler itself when silc_schedule_one + is called. After that call returns we go back to the Active Scheduler + to dispatch other active objects and to wait for next timeout. + + Wakeup of the scheduler works by simply cancelling the outstanding timeout + and issuing a zero timeout to call the silc_schedule_one again. + + If user directly calls silc_schedule_one it behaves same as on other + platforms. */ + +class SilcSymbianScheduler; +class SilcSymbianSchedulerWakeup; + +typedef struct { + SilcSymbianScheduler *timer; + SilcSymbianSchedulerWakeup *wakeup; +} *SilcSymbianInternal; + +/* SILC scheduler timer class. This handles the actual SILC Scheduler + by calling silc_schedule_one and scheduling the scheduler timeouts. */ +class SilcSymbianScheduler : public CTimer { +public: + /* Constructor */ + SilcSymbianScheduler() : CTimer(CActive::EPriorityStandard) + { + CTimer::ConstructL(); + CActiveScheduler::Add(this); + After(0); + } + + /* Destructor */ + ~SilcSymbianScheduler() + { + Cancel(); + } + + /* Timeout callback */ + virtual void RunL() + { + if (!silc_schedule_one(schedule, -1)) + s->AsyncStop(); + } + + CActiveSchedulerWait *s; + SilcSchedule schedule; +}; + +/* Scheduler wakeup class */ +class SilcSymbianSchedulerWakeup : public CActive { +public: + /* Constructor */ + SilcSymbianSchedulerWakeup() : CActive(CActive::EPriorityStandard) + { + CActiveScheduler::Add(this); + iStatus = KRequestPending; + SetActive(); + } + + /* Destructor */ + ~SilcSymbianSchedulerWakeup() + { + Cancel(); + } + + /* Wakeup */ + void Wakeup(TThreadId thread_id) + { + if (wake_signal) + return; + wake_signal = TRUE; + + TRequestStatus *status = &iStatus; + if (id != thread_id) + thread.RequestComplete(status, KErrNone); + else + User::RequestComplete(status, KErrNone); + } + + /* Timeout callback */ + virtual void RunL() + { + SILC_LOG_DEBUG(("Wakeup scheduler")); + + /* Wakeup scheduler */ + timer->Cancel(); + timer->After(0); + wake_signal = FALSE; + + iStatus = KRequestPending; + SetActive(); + } + + virtual void DoCancel() + { + + } + + RThread thread; + TThreadId id; + SilcSymbianScheduler *timer; + unsigned int wake_signal : 1; +}; + +extern "C" { + +/* Symbian's silc_schedule call. We start Active Scheduler here and start + our SILC Scheduler. The calling thread will block here. */ + +void silc_schedule(SilcSchedule schedule) +{ + SilcSymbianInternal internal = (SilcSymbianInternal)schedule->internal; + CActiveSchedulerWait *s; + + SILC_LOG_DEBUG(("Running scheduler")); + + /* Create Active Scheduler */ + s = new CActiveSchedulerWait; + SILC_ASSERT(s); + + /* Start SILC Scheduler */ + internal->timer = new SilcSymbianScheduler; + SILC_ASSERT(internal->timer); + internal->timer->schedule = schedule; + internal->timer->s = s; + internal->wakeup = new SilcSymbianSchedulerWakeup; + SILC_ASSERT(internal->wakeup); + internal->wakeup->id = RThread().Id(); + internal->wakeup->thread.Open(internal->wakeup->id); + internal->wakeup->timer = internal->timer; + + /* Start Active Scheduler */ + s->Start(); + + delete internal->wakeup; + delete internal->timer; + delete s; +} + +int silc_poll(SilcSchedule schedule, void *context) +{ + SilcSymbianInternal internal = (SilcSymbianInternal)context; + int timeout = -1; + TTime at_timeout; + + /* When user is using silc_schedule_one we don't have our timer set, + so just return immediately. */ + if (!internal->timer) + return 0; + + /* Schedule next timeout */ + if (schedule->has_timeout) + timeout = ((schedule->timeout.tv_sec * 1000) + + (schedule->timeout.tv_usec / 1000)); + + if (!timeout) + return 0; + + if (timeout == -1) + timeout = 0; + + /* Set the timeout value */ + at_timeout.HomeTime(); + while (timeout > 2100 * 1000) { + at_timeout += (TTimeIntervalMicroSeconds32)(2100 * 1000 * 1000); + timeout -= (2100 * 1000); + } + at_timeout += (TTimeIntervalMicroSeconds32)timeout; + + /* Schedule the timeout */ + internal->timer->At(at_timeout); + + /* Return special "ignore" value. Causes the scheduler to just break + the scheduler iteration and return back to its caller. */ + return -2; +} + +SilcBool silc_schedule_internal_schedule_fd(SilcSchedule schedule, + void *context, + SilcTaskFd task, + SilcTaskEvent event_mask) +{ + /* Nothing to do */ + return TRUE; +} + +void *silc_schedule_internal_init(SilcSchedule schedule, + void *app_context) +{ + SilcSymbianInternal internal; + + internal = (SilcSymbianInternal)silc_calloc(1, sizeof(*internal)); + if (!internal) + return NULL; + + return internal; +} + +void silc_schedule_internal_uninit(SilcSchedule schedule, void *context) +{ + SilcSymbianInternal internal = (SilcSymbianInternal)context; + silc_free(internal); +} + +void silc_schedule_internal_wakeup(SilcSchedule schedule, void *context) +{ +#ifdef SILC_THREADS + SilcSymbianInternal internal = (SilcSymbianInternal)context; + TThreadId id; + + if (!internal->timer) + return; + + id = RThread().Id(); + internal->wakeup->Wakeup(id); +#endif /* SILC_THREADS */ +} + +void silc_schedule_internal_signal_register(SilcSchedule schedule, + void *context, + SilcUInt32 sig, + SilcTaskCallback callback, + void *callback_context) +{ + /* Nothing to do */ +} + +void silc_schedule_internal_signal_unregister(SilcSchedule schedule, + void *context, + SilcUInt32 sig) +{ + /* Nothing to do */ +} + +void silc_schedule_internal_signals_call(SilcSchedule schedule, void *context) +{ + /* Nothing to do */ +} + +void silc_schedule_internal_signals_block(SilcSchedule schedule, void *context) +{ + /* Nothing to do */ +} + +void silc_schedule_internal_signals_unblock(SilcSchedule schedule, + void *context) +{ + /* Nothing to do */ +} + +EXPORT_C const SilcScheduleOps schedule_ops = +{ + silc_schedule_internal_init, + silc_schedule_internal_uninit, + silc_poll, + silc_schedule_internal_schedule_fd, + silc_schedule_internal_wakeup, + silc_schedule_internal_signal_register, + silc_schedule_internal_signal_unregister, + silc_schedule_internal_signals_call, + silc_schedule_internal_signals_block, + silc_schedule_internal_signals_unblock, +}; + +} /* extern "C" */ diff --git a/lib/silcutil/symbian/silcsymbiansocketstream.cpp b/lib/silcutil/symbian/silcsymbiansocketstream.cpp index ee7d23dd..cce36443 100644 --- a/lib/silcutil/symbian/silcsymbiansocketstream.cpp +++ b/lib/silcutil/symbian/silcsymbiansocketstream.cpp @@ -51,7 +51,8 @@ public: { SILC_LOG_DEBUG(("Send()")); s->sock->Send(buf, 0, iStatus, ret_len); - SetActive(); + if (!IsActive()) + SetActive(); } /* Send data */ @@ -67,7 +68,8 @@ public: tmp = (TText *)remote_ip; if (remote.Input(tmp) == KErrNone) { s->sock->SendTo(buf, remote, 0, iStatus, ret_len); - SetActive(); + if (!IsActive()) + SetActive(); } } @@ -123,7 +125,7 @@ public: { SILC_LOG_DEBUG(("Read()")); - if (!s->stream || s->stream->connected) + if (s->stream && s->stream->connected) s->sock->RecvOneOrMore(inbuf, 0, iStatus, read_len); else s->sock->RecvFrom(inbuf, remote, 0, iStatus); @@ -202,6 +204,7 @@ SilcSymbianSocket *silc_create_symbian_socket(RSocket *sock, silc_free(stream); return NULL; } + stream->send->s = stream; stream->receive = new SilcSymbianSocketReceive; if (!stream->receive) { @@ -209,6 +212,7 @@ SilcSymbianSocket *silc_create_symbian_socket(RSocket *sock, silc_free(stream); return NULL; } + stream->receive->s = stream; stream->receive->inbuf_ptr = NULL; stream->receive->inbuf_len = 0; diff --git a/lib/silcutil/symbian/silcsymbianthread.cpp b/lib/silcutil/symbian/silcsymbianthread.cpp index 5595fb76..f3aa6f26 100644 --- a/lib/silcutil/symbian/silcsymbianthread.cpp +++ b/lib/silcutil/symbian/silcsymbianthread.cpp @@ -18,6 +18,7 @@ */ #include "silc.h" +#include #include /**************************** SILC Thread API *******************************/ @@ -25,7 +26,7 @@ extern "C" { /* Thread structure for Symbian */ -typedef struct { +struct SilcSymbianThread { #ifdef SILC_THREADS SilcThreadStart start_func; void *context; @@ -33,25 +34,36 @@ typedef struct { #else void *tmp; #endif -} *SilcSymbianThread; +}; /* The actual thread function */ static TInt silc_thread_start(TAny *context) { #ifdef SILC_THREADS - SilcSymbianThread tc = (SilcSymbianThread)context; + SilcSymbianThread *tc = (SilcSymbianThread *)context; SilcThreadStart start_func = tc->start_func; void *user_context = tc->context; SilcBool waitable = tc->waitable; + void *ret = NULL; silc_free(tc); - /* Call the thread function */ - if (waitable) - silc_thread_exit(start_func(user_context)); - else - start_func(user_context); + CTrapCleanup *cs = CTrapCleanup::New(); + if (cs) { + CActiveScheduler *s = new CActiveScheduler; + if(s) { + CActiveScheduler::Install(s); + + /* Call the thread function */ + TRAPD(ret_val, ret = start_func(user_context)); + + delete s; + } + delete cs; + } + + silc_thread_exit(ret); #endif return KErrNone; @@ -63,14 +75,15 @@ SilcThread silc_thread_create(SilcThreadStart start_func, void *context, SilcBool waitable) { #ifdef SILC_THREADS - SilcSymbianThread tc; + SilcSymbianThread *tc; RThread *thread; TInt ret; - TBuf<32> name; + char tmp[24]; + SilcUInt16 wname[24]; SILC_LOG_DEBUG(("Creating new thread")); - tc = (SilcSymbianThread)silc_calloc(1, sizeof(*thread)); + tc = (SilcSymbianThread *)silc_calloc(1, sizeof(*tc)); if (!tc) return NULL; tc->start_func = start_func; @@ -78,18 +91,21 @@ SilcThread silc_thread_create(SilcThreadStart start_func, void *context, tc->waitable = waitable; /* Allocate thread */ - thread = new RThread(); + thread = new RThread; if (!thread) { silc_free(tc); return NULL; } /* Create the thread */ - name = (TText *)silc_time_string(0); - ret = thread->Create(name, silc_thread_start, 8192, 4096, 1024 * 1024, - (TAny *)tc); + silc_snprintf(tmp, sizeof(tmp), "thread-%p", tc); + silc_utf8_c2w((const unsigned char *)tmp, strlen(tmp), wname, + sizeof(wname) / sizeof(wname[0])); + TBuf<24> name((unsigned short *)wname); + name.PtrZ(); + ret = thread->Create(name, silc_thread_start, 8192, NULL, tc); if (ret != KErrNone) { - SILC_LOG_ERROR(("Could not create new thread")); + SILC_LOG_ERROR(("Could not create new thread, error %d", ret)); delete thread; silc_free(tc); return NULL; @@ -380,13 +396,17 @@ SilcBool silc_cond_timedwait(SilcCond cond, SilcMutex mutex, int timeout) { #ifdef SILC_THREADS - if (timeout) - return (cond->cond->TimedWait(*mutex->mutex, (TInt)timeout * 1000) == - KErrNone); + TInt ret; + if (timeout) { + ret = cond->cond->TimedWait(*mutex->mutex, (TInt)timeout * 1000); + if (ret != KErrNone) + SILC_LOG_DEBUG(("TimedWait returned %d", ret)); + return ret != KErrTimedOut; + } return (cond->cond->Wait(*mutex->mutex) == KErrNone); #else return FALSE; #endif /* SILC_THREADS*/ } -} /* extern "C" */ \ No newline at end of file +} /* extern "C" */ diff --git a/lib/silcutil/symbian/silcsymbianutil.cpp b/lib/silcutil/symbian/silcsymbianutil.cpp index 270b14ff..691ec677 100644 --- a/lib/silcutil/symbian/silcsymbianutil.cpp +++ b/lib/silcutil/symbian/silcsymbianutil.cpp @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2006 Pekka Riikonen + Copyright (C) 2006 - 2007 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -27,6 +27,7 @@ extern "C" { char *silc_get_username() { +#if 0 char *logname = NULL; logname = getlogin(); @@ -41,12 +42,16 @@ char *silc_get_username() } return strdup(logname); +#else + return strdup("Symbian"); +#endif /* 0 */ } /* Returns the real name of ther user. */ char *silc_get_real_name() { +#if 0 char *realname = NULL; struct passwd *pw; @@ -63,6 +68,9 @@ char *silc_get_real_name() realname = strdup(pw->pw_gecos); return realname; +#else + return strdup("Lastname"); +#endif /* 0 */ } /* Return current time to struct timeval. */ @@ -84,7 +92,8 @@ void silc_symbian_usleep(long microseconds) void silc_symbian_debug(const char *function, int line, char *string) { - RDebug::Print(_L("%s:%d: %s"), function, line, string); + fprintf(stderr, "%s:%d: %s\n", function, line, string); + // RDebug::Print(_L("%s:%d: %s"), function, line, string); } } /* extern "C" */ diff --git a/symbian/silcdefs.h b/symbian/silcdefs.h index e307a5df..75aba789 100644 --- a/symbian/silcdefs.h +++ b/symbian/silcdefs.h @@ -186,7 +186,7 @@ /* HAVE_VA_COPY */ //#define HAVE_VA_COPY -#define HAVE_VA_COPY_AARRAY +#define HAVE_VA_COPY_ARRAY /* Name of package */ #define PACKAGE "silc-toolkit" -- 2.24.0