Added SILC Server library.
[silc.git] / lib / silcutil / silcfdstream.c
index d1fc6b534dd942660b52cd8e7cb46b36d492476b..db9bd9d724185d0396b454b5857d301eb7790c84 100644 (file)
@@ -17,7 +17,7 @@
 
 */
 
-#include "silcincludes.h"
+#include "silc.h"
 
 #define SILC_IS_FD_STREAM(s) (s->ops == &silc_fd_stream_ops)
 
@@ -59,21 +59,20 @@ SILC_TASK_CALLBACK(silc_fd_stream_io)
 
 /* Create file descriptor stream */
 
-SilcStream silc_fd_stream_create(int fd, SilcSchedule schedule)
+SilcStream silc_fd_stream_create(int fd)
 {
   if (fd < 1)
     return NULL;
-  return silc_fd_stream_create2(fd, 0, schedule);
+  return silc_fd_stream_create2(fd, 0);
 }
 
 /* Create stream with two file descriptors */
 
-SilcStream silc_fd_stream_create2(int read_fd, int write_fd,
-                                 SilcSchedule schedule)
+SilcStream silc_fd_stream_create2(int read_fd, int write_fd)
 {
   SilcFDStream stream;
 
-  if (read_fd < 1 && write_fd < 1)
+  if (read_fd < 1)
     return NULL;
 
   stream = silc_calloc(1, sizeof(*stream));
@@ -83,29 +82,40 @@ SilcStream silc_fd_stream_create2(int read_fd, int write_fd,
   SILC_LOG_DEBUG(("Creating new fd stream %p", stream));
 
   stream->ops = &silc_fd_stream_ops;
-  stream->schedule = schedule;
   stream->fd1 = read_fd;
-  stream->fd1 = write_fd;
-
-  /* Schedule the file descriptors */
-  if (write_fd > 0) {
-    silc_schedule_task_add_fd(schedule, write_fd, silc_fd_stream_io, stream);
-    silc_net_set_socket_nonblock(write_fd);
-  }
-  if (read_fd > 0) {
-    silc_schedule_task_add_fd(schedule, read_fd, silc_fd_stream_io, stream);
-    silc_schedule_set_listen_fd(schedule, read_fd, SILC_TASK_READ, FALSE);
-    silc_net_set_socket_nonblock(read_fd);
-    if (write_fd < 1)
-      write_fd = read_fd;
-  }
+  stream->fd2 = write_fd;
 
   return stream;
 }
 
+/* Create by opening file */
+
+SilcStream silc_fd_stream_file(const char *filename,
+                              SilcBool reading, SilcBool writing)
+{
+  int fd, flags = 0;
+
+  if (!filename)
+    return NULL;
+
+  if (reading)
+    flags |= O_RDONLY;
+  if (writing)
+    flags |= O_CREAT | O_WRONLY;
+  if (reading && writing)
+    flags |= O_CREAT | O_RDWR;
+
+  fd = silc_file_open(filename, flags);
+  if (fd < 0)
+    return NULL;
+
+  return silc_fd_stream_create(fd);
+}
+
 /* Return fds */
 
-SilcBool silc_fd_stream_get_info(SilcStream stream, int *read_fd, int *write_fd)
+SilcBool silc_fd_stream_get_info(SilcStream stream, int *read_fd,
+                                int *write_fd)
 {
   SilcFDStream fd_stream = stream;
 
@@ -142,6 +152,8 @@ int silc_fd_stream_read(SilcStream stream, unsigned char *buf,
 
   if (!SILC_IS_FD_STREAM(fd_stream))
     return -2;
+  if (!fd_stream->notifier)
+    return -2;
 
   SILC_LOG_DEBUG(("Reading data from fd %d", fd_stream->fd1));
 
@@ -178,6 +190,8 @@ int silc_fd_stream_write(SilcStream stream, const unsigned char *data,
 
   if (!SILC_IS_FD_STREAM(fd_stream))
     return -2;
+  if (!fd_stream->notifier)
+    return -2;
 
   SILC_LOG_DEBUG(("Writing data to fd %d", fd_stream->fd2));
 
@@ -215,10 +229,14 @@ SilcBool silc_fd_stream_close(SilcStream stream)
   if (!SILC_IS_FD_STREAM(fd_stream))
     return FALSE;
 
-  if (fd_stream->fd1 > 0)
+  if (fd_stream->fd1 > 0) {
     silc_file_close(fd_stream->fd1);
-  if (fd_stream->fd2 > 0 && fd_stream->fd2 != fd_stream->fd1)
+    silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd1);
+  }
+  if (fd_stream->fd2 > 0 && fd_stream->fd2 != fd_stream->fd1) {
     silc_file_close(fd_stream->fd2);
+    silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd2);
+  }
 
   return TRUE;
 }
@@ -233,12 +251,15 @@ void silc_fd_stream_destroy(SilcStream stream)
     return;
 
   silc_fd_stream_close(stream);
+  silc_schedule_task_del_by_fd(fd_stream->schedule, fd_stream->fd1);
+  silc_schedule_task_del_by_fd(fd_stream->schedule, fd_stream->fd2);
   silc_free(stream);
 }
 
 /* Sets stream notification callback for the stream */
 
 void silc_fd_stream_notifier(SilcStream stream,
+                            SilcSchedule schedule,
                             SilcStreamNotifier callback,
                             void *context)
 {
@@ -251,6 +272,40 @@ void silc_fd_stream_notifier(SilcStream stream,
 
   fd_stream->notifier = callback;
   fd_stream->notifier_context = context;
+  fd_stream->schedule = schedule;
+
+  /* Schedule the file descriptors */
+  if (schedule) {
+    if (fd_stream->fd2 > 0) {
+      silc_schedule_task_add_fd(schedule, fd_stream->fd2,
+                               silc_fd_stream_io, stream);
+      silc_file_set_nonblock(fd_stream->fd2);
+    }
+    if (fd_stream->fd1 > 0) {
+      silc_schedule_task_add_fd(schedule, fd_stream->fd1,
+                               silc_fd_stream_io, stream);
+      silc_schedule_set_listen_fd(schedule, fd_stream->fd1,
+                                 SILC_TASK_READ, FALSE);
+      silc_file_set_nonblock(fd_stream->fd1);;
+      if (fd_stream->fd2 < 1)
+       fd_stream->fd2 = fd_stream->fd1;
+    }
+  } else {
+    silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd1);
+    silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd2);
+  }
+}
+
+/* Return schedule */
+
+SilcSchedule silc_fd_stream_get_schedule(SilcStream stream)
+{
+  SilcFDStream fd_stream = stream;
+
+  if (!SILC_IS_FD_STREAM(fd_stream))
+    return NULL;
+
+  return fd_stream->schedule;
 }
 
 /* File descriptor stream operations */
@@ -261,4 +316,5 @@ const SilcStreamOps silc_fd_stream_ops =
   silc_fd_stream_close,
   silc_fd_stream_destroy,
   silc_fd_stream_notifier,
+  silc_fd_stream_get_schedule
 };