Porting Toolkit to Symbian. It should work while some sporadic
[silc.git] / lib / silcutil / silcsocketstream.c
index 1bd6b8b32144b79c18b25048db5f23640fae0555..e4b59f5a601c6d0019632438514f780a48729507 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2005 - 2006 Pekka Riikonen
+  Copyright (C) 2005 - 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
 
 /************************** Types and definitions ***************************/
 
-#define SILC_IS_SOCKET_STREAM(s) (s->ops == &silc_socket_stream_ops)
-#define SILC_IS_SOCKET_STREAM_UDP(s) (s->ops == &silc_socket_udp_stream_ops)
-
-const SilcStreamOps silc_socket_stream_ops;
-const SilcStreamOps silc_socket_udp_stream_ops;
-
-/* Platform specific functions */
+/* Stream operation functions (platform specific) */
 int silc_socket_stream_read(SilcStream stream, unsigned char *buf,
                            SilcUInt32 buf_len);
 int silc_socket_stream_write(SilcStream stream, const unsigned char *data,
@@ -38,6 +32,13 @@ int silc_socket_udp_stream_read(SilcStream stream, unsigned char *buf,
                                SilcUInt32 buf_len);
 int silc_socket_udp_stream_write(SilcStream stream, const unsigned char *data,
                                 SilcUInt32 data_len);
+SilcBool silc_socket_stream_close(SilcStream stream);
+void silc_socket_stream_destroy(SilcStream stream);
+SilcBool silc_socket_stream_notifier(SilcStream stream,
+                                    SilcSchedule schedule,
+                                    SilcStreamNotifier callback,
+                                    void *context);
+SilcSchedule silc_socket_stream_get_schedule(SilcStream stream);
 
 /* Internal async host lookup context. */
 typedef struct {
@@ -53,30 +54,6 @@ typedef struct {
 
 /************************ Static utility functions **************************/
 
-/* The IO process callback that calls the notifier callback to upper
-   layer. */
-
-SILC_TASK_CALLBACK(silc_socket_stream_io)
-{
-  SilcSocketStream stream = context;
-
-  if (!stream->notifier)
-    return;
-
-  switch (type) {
-  case SILC_TASK_WRITE:
-    stream->notifier(stream, SILC_STREAM_CAN_WRITE, stream->notifier_context);
-    break;
-
-  case SILC_TASK_READ:
-    stream->notifier(stream, SILC_STREAM_CAN_READ, stream->notifier_context);
-    break;
-
-  default:
-    break;
-  }
-}
-
 /* Finishing timeout callback that will actually call the user specified
    host lookup callback.  This is executed back in the calling thread and
    not in the lookup thread. */
@@ -88,20 +65,16 @@ SILC_TASK_CALLBACK(silc_socket_host_lookup_finish)
 
   if (lookup->aborted) {
     SILC_LOG_DEBUG(("Socket stream creation was aborted"));
-    silc_net_close_connection(stream->sock);
-    silc_free(stream->ip);
-    silc_free(stream->hostname);
-    silc_free(stream);
+    stream->schedule = NULL;
+    silc_socket_stream_destroy(stream);
     silc_free(lookup);
     return;
   }
 
   if (lookup->status != SILC_SOCKET_OK) {
-    SILC_LOG_DEBUG(("Socket stream failed"));
-    silc_net_close_connection(stream->sock);
-    silc_free(stream->ip);
-    silc_free(stream->hostname);
-    silc_free(stream);
+    SILC_LOG_DEBUG(("Socket stream lookup failed"));
+    stream->schedule = NULL;
+    silc_socket_stream_destroy(stream);
     stream = lookup->stream = NULL;
   }
 
@@ -170,7 +143,7 @@ static void silc_socket_host_lookup_abort(SilcAsyncOperation op,
 /* Creates TCP socket stream */
 
 SilcAsyncOperation
-silc_socket_tcp_stream_create(int sock, SilcBool lookup,
+silc_socket_tcp_stream_create(SilcSocket sock, SilcBool lookup,
                              SilcBool require_fqdn,
                              SilcSchedule schedule,
                              SilcSocketStreamCallback callback,
@@ -179,6 +152,13 @@ silc_socket_tcp_stream_create(int sock, SilcBool lookup,
   SilcSocketStream stream;
   SilcSocketHostLookup l;
 
+  if (!sock || !schedule) {
+    SILC_LOG_ERROR(("Missing arguments to silc_socket_tcp_stream_create"));
+    if (callback)
+      callback(SILC_SOCKET_ERROR, NULL, context);
+    return NULL;
+  }
+
   stream = silc_calloc(1, sizeof(*stream));
   if (!stream) {
     if (callback)
@@ -186,11 +166,12 @@ silc_socket_tcp_stream_create(int sock, SilcBool lookup,
     return NULL;
   }
 
-  SILC_LOG_DEBUG(("Creating TCP socket stream %p", stream));
+  SILC_LOG_DEBUG(("Creating TCP socket stream %p, sock %lu", stream, sock));
 
   stream->ops = &silc_socket_stream_ops;
   stream->sock = sock;
   stream->schedule = schedule;
+  stream->connected = TRUE;
 
   l = silc_calloc(1, sizeof(*l));
   if (!l) {
@@ -232,7 +213,7 @@ silc_socket_tcp_stream_create(int sock, SilcBool lookup,
 
 /* Creates UDP socket stream */
 
-SilcStream silc_socket_udp_stream_create(int sock, SilcBool ipv6,
+SilcStream silc_socket_udp_stream_create(SilcSocket sock, SilcBool ipv6,
                                         SilcBool connected,
                                         SilcSchedule schedule)
 {
@@ -271,7 +252,7 @@ SilcBool silc_socket_stream_is_udp(SilcStream stream, SilcBool *connected)
 /* Returns socket stream information */
 
 SilcBool silc_socket_stream_get_info(SilcStream stream,
-                                    int *sock, const char **hostname,
+                                    SilcSocket *sock, const char **hostname,
                                     const char **ip, SilcUInt16 *port)
 {
   SilcSocketStream socket_stream = stream;
@@ -282,20 +263,20 @@ SilcBool silc_socket_stream_get_info(SilcStream stream,
 
   if (sock)
     *sock = socket_stream->sock;
-  if (hostname) {
-    if (!socket_stream->hostname)
+  if (port) {
+    if (!socket_stream->port)
       return FALSE;
-    *hostname = socket_stream->hostname;
+    *port = socket_stream->port;
   }
   if (ip) {
     if (!socket_stream->ip)
       return FALSE;
     *ip = socket_stream->ip;
   }
-  if (port) {
-    if (!socket_stream->port)
+  if (hostname) {
+    if (!socket_stream->hostname)
       return FALSE;
-    *port = socket_stream->port;
+    *hostname = socket_stream->hostname;
   }
 
   return TRUE;
@@ -396,91 +377,6 @@ SilcBool silc_socket_stream_set_qos(SilcStream stream,
   return TRUE;
 }
 
-/* Closes socket */
-
-SilcBool silc_socket_stream_close(SilcStream stream)
-{
-  SilcSocketStream socket_stream = stream;
-
-  if (!SILC_IS_SOCKET_STREAM(socket_stream) &&
-      !SILC_IS_SOCKET_STREAM_UDP(socket_stream))
-    return FALSE;
-
-  silc_schedule_unset_listen_fd(socket_stream->schedule, socket_stream->sock);
-  silc_net_close_connection(socket_stream->sock);
-
-  return TRUE;
-}
-
-/* Destroys the stream */
-
-void silc_socket_stream_destroy(SilcStream stream)
-{
-  SilcSocketStream socket_stream = stream;
-
-  if (!SILC_IS_SOCKET_STREAM(socket_stream) &&
-      !SILC_IS_SOCKET_STREAM_UDP(socket_stream))
-    return;
-
-  silc_socket_stream_close(socket_stream);
-  silc_free(socket_stream->ip);
-  silc_free(socket_stream->hostname);
-  silc_schedule_task_del_by_fd(socket_stream->schedule, socket_stream->sock);
-
-  if (socket_stream->qos) {
-    silc_schedule_task_del_by_context(socket_stream->schedule,
-                                     socket_stream->qos);
-    if (socket_stream->qos->buffer) {
-      memset(socket_stream->qos->buffer, 0,
-            socket_stream->qos->read_limit_bytes);
-      silc_free(socket_stream->qos->buffer);
-    }
-    silc_free(socket_stream->qos);
-  }
-
-  silc_schedule_wakeup(socket_stream->schedule);
-
-  silc_free(socket_stream);
-}
-
-/* Sets stream notification callback for the stream */
-
-void silc_socket_stream_notifier(SilcStream stream,
-                                SilcSchedule schedule,
-                                SilcStreamNotifier callback,
-                                void *context)
-{
-  SilcSocketStream socket_stream = stream;
-
-  if (!SILC_IS_SOCKET_STREAM(socket_stream) &&
-      !SILC_IS_SOCKET_STREAM_UDP(socket_stream))
-    return;
-
-  SILC_LOG_DEBUG(("Setting stream notifier callback"));
-
-  socket_stream->notifier = callback;
-  socket_stream->notifier_context = context;
-  socket_stream->schedule = schedule;
-
-  if (socket_stream->notifier) {
-    /* Add the socket to scheduler.  Safe to call if already added. */
-    silc_schedule_task_add_fd(socket_stream->schedule, socket_stream->sock,
-                             silc_socket_stream_io, socket_stream);
-
-    /* Initially set socket for reading */
-    silc_schedule_set_listen_fd(socket_stream->schedule, socket_stream->sock,
-                               SILC_TASK_READ, FALSE);
-    silc_schedule_wakeup(socket_stream->schedule);
-  } else {
-    /* Unschedule the socket */
-    silc_schedule_unset_listen_fd(socket_stream->schedule,
-                                 socket_stream->sock);
-    silc_schedule_task_del_by_fd(socket_stream->schedule,
-                                socket_stream->sock);
-    silc_schedule_wakeup(socket_stream->schedule);
-  }
-}
-
 /* Return associated scheduler */
 
 SilcSchedule silc_socket_stream_get_schedule(SilcStream stream)