Porting Toolkit to Symbian. It should work while some sporadic silc.toolkit.1.1.beta3
authorPekka Riikonen <priikone@silcnet.org>
Thu, 17 May 2007 14:09:35 +0000 (14:09 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Thu, 17 May 2007 14:09:35 +0000 (14:09 +0000)
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
lib/silcutil/silcschedule.c
lib/silcutil/silcschedule.h
lib/silcutil/silcsocketstream.c
lib/silcutil/silcthread.h
lib/silcutil/symbian/silcsymbiannet.cpp
lib/silcutil/symbian/silcsymbianscheduler.cpp
lib/silcutil/symbian/silcsymbiansocketstream.cpp
lib/silcutil/symbian/silcsymbianthread.cpp
lib/silcutil/symbian/silcsymbianutil.cpp
symbian/silcdefs.h

index 84fe4dc9eb221efba4796501b416ea39be682f8f..f37cf93934c33bd77d04e8d4b98de0c1dc1258e0 100644 (file)
@@ -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.
index 3853a1bb7f3ca808398699daab1248804153f866..6d3f09e1c3d3794f4776ea5211a4115c1492494c 100644 (file)
@@ -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;
 }
 
index cfcdffbc9134e2d3e6415bef69f482d7c57d6eff..e92bb830e45e989ad4e234c7d63227ff2f79206a 100644 (file)
@@ -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);
index 3140b6d92a98131caaaf96fd065fd8716fb3c7dc..e4b59f5a601c6d0019632438514f780a48729507 100644 (file)
@@ -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) {
index c6429a9b63740c39791d0b5f29a17c0f41718664..3a4036f6459ee1c5a3d8a0742fe6fd3f8bf80ab1 100644 (file)
@@ -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);
index f297b628aed052aad5ca727a6d6e570c21133b95..25e7ad2f7b2fdd840fa71fa44220bb2b226bfaae 100644 (file)
 #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" */
index f6f42cdcfb81526c7c9f1a327dcc2698dffb1848..fd1310244f84b9a6fa7aea84648686010e475a74 100644 (file)
-/*\r
-\r
-  silcsymbianschduler.cpp\r
-\r
-  Author: Pekka Riikonen <priikone@silcnet.org>\r
-\r
-  Copyright (C) 1998 - 2007 Pekka Riikonen\r
-\r
-  This program is free software; you can redistribute it and/or modify\r
-  it under the terms of the GNU General Public License as published by\r
-  the Free Software Foundation; version 2 of the License.\r
-\r
-  This program is distributed in the hope that it will be useful,\r
-  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-  GNU General Public License for more details.\r
-\r
-*/\r
-\r
-/* On symbian the SILC Scheduler doesn't do anything.  All timeout tasks\r
-   are dispatched by the generic scheduler implementation.  Sockets and\r
-   file descriptors are dispatched automatically in their class\r
-   implementation, so adding FD Tasks on Symbian doesn't do anything.\r
-\r
-   This also means that on Symbian the SILC Scheduler always returns\r
-   immediately.  Because FD tasks use the Symbian scheduler the performance\r
-   is as good as it can be.  For timeout tasks the performance is not an\r
-   issue. */\r
-\r
-#include "silc.h"\r
-\r
-extern "C" {\r
-\r
-int silc_poll(SilcSchedule schedule, void *context)\r
-{\r
-  /* Return immediately, timeout. */\r
-  return 0;\r
-}\r
-\r
-SilcBool silc_schedule_internal_schedule_fd(SilcSchedule schedule,\r
-                                           void *context,\r
-                                           SilcTaskFd task,\r
-                                           SilcTaskEvent event_mask)\r
-{\r
-  /* Nothing to do */\r
-  return TRUE;\r
-}\r
-\r
-void *silc_schedule_internal_init(SilcSchedule schedule,\r
-                                 void *app_context)\r
-{\r
-  /* Nothing to do */\r
-  return (void *)1;\r
-}\r
-\r
-\r
-void silc_schedule_internal_uninit(SilcSchedule schedule, void *context)\r
-{\r
-  /* Nothing to do */\r
-}\r
-\r
-void silc_schedule_internal_wakeup(SilcSchedule schedule, void *context)\r
-{\r
-  /* Nothing to do */\r
-}\r
-\r
-void silc_schedule_internal_signal_register(SilcSchedule schedule,\r
-                                           void *context,\r
-                                           SilcUInt32 sig,\r
-                                            SilcTaskCallback callback,\r
-                                            void *callback_context)\r
-{\r
-  /* Nothing to do */\r
-}\r
-\r
-void silc_schedule_internal_signal_unregister(SilcSchedule schedule,\r
-                                             void *context,\r
-                                             SilcUInt32 sig)\r
-{\r
-  /* Nothing to do */\r
-}\r
-\r
-void silc_schedule_internal_signals_call(SilcSchedule schedule, void *context)\r
-{\r
-  /* Nothing to do */\r
-}\r
-\r
-void silc_schedule_internal_signals_block(SilcSchedule schedule, void *context)\r
-{\r
-  /* Nothing to do */\r
-}\r
-\r
-void silc_schedule_internal_signals_unblock(SilcSchedule schedule,\r
-                                           void *context)\r
-{\r
-  /* Nothing to do */\r
-}\r
-\r
-EXPORT_C const SilcScheduleOps schedule_ops =\r
-{\r
-  silc_schedule_internal_init,\r
-  silc_schedule_internal_uninit,\r
-  silc_poll,\r
-  silc_schedule_internal_schedule_fd,\r
-  silc_schedule_internal_wakeup,\r
-  silc_schedule_internal_signal_register,\r
-  silc_schedule_internal_signal_unregister,\r
-  silc_schedule_internal_signals_call,\r
-  silc_schedule_internal_signals_block,\r
-  silc_schedule_internal_signals_unblock,\r
-};\r
-\r
-} /* extern "C" */
\ No newline at end of file
+/*
+
+  silcsymbianscheduler.cpp
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  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 <e32base.h>
+
+/* 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" */
index ee7d23ddb71ede7097cbaf8b19f157dad598c0af..cce36443ad519803c9f3bda1cfc8d68ec1275c04 100644 (file)
@@ -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;
 
index 5595fb76c8858f5e4c26933bffc97ecba5c0ade8..f3aa6f26a0dc29e64c7b91e90f6bea244fa90502 100644 (file)
@@ -18,6 +18,7 @@
 */
 
 #include "silc.h"
+#include <e32base.h>
 #include <e32std.h>
 
 /**************************** 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" */
index 270b14ff5476b2c6e23d4f07fcc9ebf7ec27b98b..691ec677d4f4b386bd9a01ea625c3fc5dbbc1c08 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  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" */
index e307a5df3af5b1dd264abde1f686339fe53e1e0c..75aba7895e199acba5a8d48405552c01c98deabb 100644 (file)
 
 /* HAVE_VA_COPY */
 //#define HAVE_VA_COPY
-#define HAVE_VA_COPY_AARRAY
+#define HAVE_VA_COPY_ARRAY
 
 /* Name of package */
 #define PACKAGE "silc-toolkit"