Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2005 Pekka Riikonen
+ Copyright (C) 2005 - 2008 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
#include "silc.h"
-#define SILC_IS_FD_STREAM(s) (s->ops == &silc_fd_stream_ops)
+/************************** Types and definitions ***************************/
+
+#define SILC_IS_FD_STREAM(s) (s && s->ops == &silc_fd_stream_ops)
const SilcStreamOps silc_fd_stream_ops;
int error;
} *SilcFDStream;
+
+/************************ Static utility functions **************************/
+
/* The IO process callback that calls the notifier callback to upper layer. */
SILC_TASK_CALLBACK(silc_fd_stream_io)
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;
+ case SILC_TASK_WRITE:
+ stream->notifier(stream, SILC_STREAM_CAN_WRITE, stream->notifier_context);
+ break;
+
default:
break;
}
}
+
+/****************************** Public API **********************************/
+
/* Create file descriptor stream */
SilcStream silc_fd_stream_create(int fd)
{
SilcFDStream stream;
- if (read_fd < 1)
- return NULL;
-
stream = silc_calloc(1, sizeof(*stream));
if (!stream)
return NULL;
/* Create by opening file */
-SilcStream silc_fd_stream_file(const char *filename,
- SilcBool reading, SilcBool writing)
+SilcStream silc_fd_stream_file(const char *filename, SilcBool reading,
+ SilcBool writing)
{
- int fd, flags = 0;
+ const char *read_file = NULL, *write_file = NULL;
if (!filename)
return NULL;
- if (reading)
- flags |= O_RDONLY;
if (writing)
- flags |= O_CREAT | O_WRONLY;
- if (reading && writing)
- flags |= O_CREAT | O_RDWR;
+ write_file = filename;
+ if (reading)
+ read_file = filename;
- fd = silc_file_open(filename, flags);
- if (fd < 0)
- return NULL;
+ return silc_fd_stream_file2(read_file, write_file);
+}
+
+/* Create by opening two files */
+
+SilcStream silc_fd_stream_file2(const char *read_file, const char *write_file)
+{
+ SilcStream stream;
+ int fd1 = 0, fd2 = 0;
+
+ SILC_LOG_DEBUG(("Creating new fd stream for reading `%s' and writing `%s'",
+ read_file ? read_file : "(none)",
+ write_file ? write_file : "(none)"));
+
+ if (write_file) {
+ fd2 = silc_file_open(write_file, O_CREAT | O_WRONLY);
+ if (fd2 < 0) {
+ silc_file_close(fd1);
+ return NULL;
+ }
+ }
+
+ if (read_file) {
+ fd1 = silc_file_open(read_file, O_RDONLY);
+ if (fd1 < 0)
+ return NULL;
+ }
- return silc_fd_stream_create(fd);
+ stream = silc_fd_stream_create2(fd1, fd2);
+ if (!stream) {
+ silc_file_close(fd1);
+ silc_file_close(fd2);
+ }
+
+ return stream;
}
/* Return fds */
SilcFDStream fd_stream = stream;
int len = 0;
- if (!SILC_IS_FD_STREAM(fd_stream))
- return -2;
if (!fd_stream->notifier)
return -2;
SilcFDStream fd_stream = stream;
int ret;
- if (!SILC_IS_FD_STREAM(fd_stream))
- return -2;
if (!fd_stream->notifier)
return -2;
{
SilcFDStream fd_stream = stream;
- if (!SILC_IS_FD_STREAM(fd_stream))
- return FALSE;
-
if (fd_stream->fd1 > 0) {
silc_file_close(fd_stream->fd1);
- silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd1);
+ if (fd_stream->schedule) {
+ silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd1);
+ silc_schedule_task_del_by_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);
+ if (fd_stream->schedule) {
+ silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd2);
+ silc_schedule_task_del_by_fd(fd_stream->schedule, fd_stream->fd2);
+ }
}
return TRUE;
void silc_fd_stream_destroy(SilcStream stream)
{
- SilcFDStream fd_stream = stream;
-
- if (!SILC_IS_FD_STREAM(fd_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)
+SilcBool silc_fd_stream_notifier(SilcStream stream,
+ SilcSchedule schedule,
+ SilcStreamNotifier callback,
+ void *context)
{
SilcFDStream fd_stream = stream;
- if (!SILC_IS_FD_STREAM(fd_stream))
- return;
-
SILC_LOG_DEBUG(("Setting stream notifier callback"));
fd_stream->notifier = callback;
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);;
+ 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);
+ if (fd_stream->schedule) {
+ silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd1);
+ silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd2);
+ silc_schedule_task_del_by_fd(fd_stream->schedule, fd_stream->fd1);
+ silc_schedule_task_del_by_fd(fd_stream->schedule, fd_stream->fd2);
+ }
}
+
+ return TRUE;
}
/* 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;
}