in way.
--HG--
branch : HEAD
conn->input = i_stream_create_file(fd, default_pool, MAX_INBUF_SIZE,
FALSE);
conn->output = o_stream_create_file(fd, default_pool, MAX_OUTBUF_SIZE,
- IO_PRIORITY_DEFAULT, FALSE);
+ FALSE);
conn->io = io_add(fd, IO_READ, login_input, conn);
conn->pool = pool_alloconly_create("auth_request hash", 10240);
login_connections_init();
- io_listen = io_add_priority(LOGIN_LISTEN_FD, IO_PRIORITY_LOW,
- IO_READ, auth_accept, NULL);
+ io_listen = io_add(LOGIN_LISTEN_FD, IO_READ, auth_accept, NULL);
/* initialize master last - it sends the "we're ok" notification */
master_connection_init();
master_pos = 0;
output = o_stream_create_file(MASTER_SOCKET_FD, default_pool,
- MAX_OUTBUF_SIZE, IO_PRIORITY_DEFAULT,
- FALSE);
+ MAX_OUTBUF_SIZE, FALSE);
io_master = io_add(MASTER_SOCKET_FD, IO_READ, master_input, NULL);
/* just a note to master that we're ok. if we die before,
static void client_auth_abort(struct imap_client *client, const char *msg)
{
+ client->authenticating = FALSE;
+
if (client->common.auth_request != NULL) {
auth_abort_request(client->common.auth_request);
auth_request_unref(client->common.auth_request);
master_callback, &error)) {
case -1:
/* login failed */
- client->authenticating = FALSE;
client_auth_abort(client, error);
break;
master_callback, &error)) {
case -1:
/* login failed */
- client->authenticating = FALSE;
client_auth_abort(client, error);
break;
client->input = i_stream_create_file(fd, default_pool,
MAX_INBUF_SIZE, FALSE);
client->output = o_stream_create_file(fd, default_pool, MAX_OUTBUF_SIZE,
- IO_PRIORITY_DEFAULT, FALSE);
+ FALSE);
client->parser = imap_parser_create(client->input, client->output,
MAX_INBUF_SIZE,
MAX_IMAP_ARG_ELEMENTS);
client = i_new(struct client, 1);
client->input = i_stream_create_file(hin, default_pool,
MAX_INBUF_SIZE, FALSE);
- client->output = o_stream_create_file(hout, default_pool, 4096,
- IO_PRIORITY_DEFAULT, FALSE);
+ client->output = o_stream_create_file(hout, default_pool, 4096, FALSE);
/* set timeout for reading expected data (eg. APPEND). This is
different from the actual idle time. */
1024*256, 0, 0, FALSE);
i_stream_set_read_limit(input, size);
- output = o_stream_create_file(out_fd, data_stack_pool, 1024, 0, FALSE);
+ output = o_stream_create_file(out_fd, data_stack_pool, 1024, FALSE);
o_stream_set_blocking(output, 60000, NULL, NULL);
ret = o_stream_send_istream(output, input);
/* note: we can't use data_stack_pool with output stream because it's
being written to inside t_push() .. t_pop() calls */
- output = o_stream_create_file(tmp_fd, system_pool, 8192, 0, FALSE);
+ output = o_stream_create_file(tmp_fd, system_pool, 8192, FALSE);
o_stream_set_blocking(output, 60000, NULL, NULL);
failed = FALSE; seq = 1;
fname++;
t_push();
- output = o_stream_create_file(fd, data_stack_pool, 4096,
- IO_PRIORITY_DEFAULT, FALSE);
+ output = o_stream_create_file(fd, data_stack_pool, 4096, FALSE);
o_stream_set_blocking(output, 60000, NULL, NULL);
if (!mail_storage_save(ibox->box.storage, path, input, output,
t_push();
output = o_stream_create_file(ibox->index->mbox_fd, data_stack_pool,
- 4096, 0, FALSE);
+ 4096, FALSE);
o_stream_set_blocking(output, 60000, NULL, NULL);
failed = !expunge_real(ibox, rec, seq, input, output, notify);
}
ctx->output = o_stream_create_file(ibox->index->mbox_fd,
- default_pool, 4096, 0, FALSE);
+ default_pool, 4096, FALSE);
o_stream_set_blocking(ctx->output, 60000, NULL, NULL);
return ctx;
}
fd = i_stream_get_fd(input);
i_assert(fd != -1);
- output = o_stream_create_file(fd, default_pool, 4096, 0, 0);
+ output = o_stream_create_file(fd, default_pool, 4096, FALSE);
if (o_stream_seek(output, input->start_offset + input->v_offset) < 0) {
failed = TRUE;
errno = output->stream_errno;
};
struct io {
- struct io *prev, *next;
+ struct io *next;
int fd;
- int priority;
int condition;
unsigned int destroyed:1;
struct timeout *next;
struct timeval next_run;
- int msecs;
- int run_now;
- int destroyed;
+ unsigned int msecs;
+
+ unsigned int run_now:1;
+ unsigned int destroyed:1;
timeout_callback_t *callback;
void *context;
void io_loop_handle_timeouts(struct ioloop *ioloop);
/* call only when io->destroyed is TRUE */
-void io_destroy(struct ioloop *ioloop, struct io *io);
+void io_destroy(struct ioloop *ioloop, struct io **io_p);
/* call only when timeout->destroyed is TRUE */
-void timeout_destroy(struct ioloop *ioloop, struct timeout *timeout);
+void timeout_destroy(struct ioloop *ioloop, struct timeout **timeout_p);
/* I/O handler calls */
void io_loop_handle_add(struct ioloop *ioloop, int fd, int condition);
struct ioloop_handler_data *data = ioloop->handler_data;
struct pollfd *pollfd;
struct timeval tv;
- struct io *io, *next;
+ struct io *io, **io_p;
unsigned int t_id;
- int msecs, ret;
+ int msecs, ret, call;
/* get the time left for next timeout task */
msecs = io_loop_get_wait_time(ioloop->timeouts, &tv, NULL);
return;
}
- /* execute the I/O handlers in prioritized order */
- for (io = ioloop->ios; io != NULL && ret > 0; io = next) {
- next = io->next;
-
+ io_p = &ioloop->ios;
+ for (io = ioloop->ios; io != NULL && ret > 0; io = *io_p) {
if (io->destroyed) {
/* we were destroyed, and io->fd points to
-1 now, so we can't know if there was any
revents left. */
- io_destroy(ioloop, io);
+ io_destroy(ioloop, io_p);
continue;
}
i_assert(io->fd >= 0);
pollfd = &data->fds[data->fd_index[io->fd]];
- if (pollfd->revents == 0)
- continue;
- ret--;
-
- if (pollfd->revents & POLLNVAL) {
- i_error("invalid I/O fd %d, callback %p",
- io->fd, (void *) io->callback);
- pollfd->events &= ~POLLNVAL;
- pollfd->revents &= ~POLLNVAL;
- continue;
+ if (pollfd->revents != 0) {
+ ret--;
+
+ if (pollfd->revents & POLLNVAL) {
+ i_error("invalid I/O fd %d, callback %p",
+ io->fd, (void *) io->callback);
+ pollfd->events &= ~POLLNVAL;
+ pollfd->revents &= ~POLLNVAL;
+ call = FALSE;
+ } else if ((io->condition &
+ (IO_READ|IO_WRITE)) == (IO_READ|IO_WRITE)) {
+ call = TRUE;
+ pollfd->revents = 0;
+ } else if (io->condition & IO_READ) {
+ call = (pollfd->revents & IO_POLL_INPUT) != 0;
+ pollfd->revents &= ~IO_POLL_INPUT;
+ } else if (io->condition & IO_WRITE) {
+ call = (pollfd->revents & IO_POLL_OUTPUT) != 0;
+ pollfd->revents &= ~IO_POLL_OUTPUT;
+ }
+
+ if (call) {
+ t_id = t_push();
+ io->callback(io->context);
+ if (t_pop() != t_id)
+ i_panic("Leaked a t_pop() call!");
+
+ if (io->destroyed)
+ io_destroy(ioloop, io_p);
+ }
}
- if ((io->condition &
- (IO_READ|IO_WRITE)) == (IO_READ|IO_WRITE)) {
- pollfd->revents = 0;
- } else if (io->condition & IO_READ) {
- if ((pollfd->revents & IO_POLL_INPUT) == 0)
- continue;
- pollfd->revents &= ~IO_POLL_INPUT;
- } else if (io->condition & IO_WRITE) {
- if ((pollfd->revents & IO_POLL_OUTPUT) == 0)
- continue;
- pollfd->revents &= ~IO_POLL_OUTPUT;
- }
-
- t_id = t_push();
- io->callback(io->context);
- if (t_pop() != t_id)
- i_panic("Leaked a t_pop() call!");
-
- if (io->destroyed)
- io_destroy(ioloop, io);
+ io_p = &io->next;
}
}
return;
}
- /* execute the I/O handlers in prioritized order */
- for (io = ioloop->ios; io != NULL && ret > 0; io = next) {
- next = io->next;
-
+ io_p = &ioloop->ios;
+ for (io = ioloop->ios; io != NULL && ret > 0; io = *io_p) {
if (io->destroyed) {
/* we were destroyed, and io->fd points to -1 now. */
io_destroy(ioloop, io);
fd = io->fd;
condition = io->condition;
- if (!io_check_condition(fd, condition))
- continue;
+ if (io_check_condition(fd, condition)) {
+ t_id = t_push();
+ io->callback(io->context);
+ if (t_pop() != t_id)
+ i_panic("Leaked a t_pop() call!");
- t_id = t_push();
- io->callback(io->context);
- if (t_pop() != t_id)
- i_panic("Leaked a t_pop() call!");
+ if (io->destroyed)
+ io_destroy(ioloop, io_p);
- if (io->destroyed)
- io_destroy(ioloop, io);
+ ret--;
+ }
- ret--;
+ io_p = &io->next;
}
}
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-/* FIXME: inserting io is slow if there's lots of them. I should add a linked
- list of priorities pointing to first item in the list with the priority. */
-
#include "lib.h"
#include "ioloop-internal.h"
}
}
-static void io_list_insert(struct ioloop *ioloop, struct io *io)
-{
- struct io *prev, *next;
-
- prev = NULL;
- for (next = ioloop->ios; next != NULL; next = next->next) {
- if (next->priority >= io->priority)
- break;
- prev = next;
- }
-
- if (prev == NULL)
- ioloop->ios = io;
- else {
- io->prev = prev;
- prev->next = io;
- }
-
- if (next != NULL) {
- io->next = next;
- next->prev = io;
- }
-}
-
-struct io *io_add(int fd, int condition, io_callback_t *callback, void *data)
-{
- return io_add_priority(fd, IO_PRIORITY_DEFAULT,
- condition, callback, data);
-}
-
-struct io *io_add_priority(int fd, int priority, int condition,
- io_callback_t *callback, void *context)
+struct io *io_add(int fd, int condition, io_callback_t *callback, void *context)
{
struct io *io;
io = p_new(current_ioloop->pool, struct io, 1);
io->fd = fd;
- io->priority = priority;
io->condition = condition;
io->callback = callback;
current_ioloop->highest_fd = io->fd;
io_loop_handle_add(current_ioloop, io->fd, io->condition);
- io_list_insert(current_ioloop, io);
+ io->next = current_ioloop->ios;
+ current_ioloop->ios = io;
return io;
}
io->fd = -1;
}
-void io_destroy(struct ioloop *ioloop, struct io *io)
+void io_destroy(struct ioloop *ioloop, struct io **io_p)
{
- /* remove from list */
- if (io->prev == NULL)
- ioloop->ios = io->next;
- else
- io->prev->next = io->next;
-
- if (io->next != NULL)
- io->next->prev = io->prev;
+ struct io *io = *io_p;
+ /* remove from list */
+ *io_p = io->next;
p_free(ioloop->pool, io);
}
}
}
-struct timeout *timeout_add(int msecs, timeout_callback_t *callback,
+struct timeout *timeout_add(unsigned int msecs, timeout_callback_t *callback,
void *context)
{
struct timeout *timeout;
timeout->destroyed = TRUE;
}
-void timeout_destroy(struct ioloop *ioloop, struct timeout *timeout)
+void timeout_destroy(struct ioloop *ioloop, struct timeout **timeout_p)
{
- struct timeout **t;
-
- for (t = &ioloop->timeouts; *t != NULL; t = &(*t)->next) {
- if (*t == timeout)
- break;
- }
- *t = timeout->next;
+ struct timeout *timeout = *timeout_p;
+ *timeout_p = timeout->next;
p_free(ioloop->pool, timeout);
}
void io_loop_handle_timeouts(struct ioloop *ioloop)
{
- struct timeout *t, *next;
+ struct timeout *t, **t_p;
struct timeval tv;
unsigned int t_id;
if (ioloop->timeouts == NULL || !ioloop->timeouts->run_now)
return;
- for (t = ioloop->timeouts; t != NULL; t = next) {
- next = t->next;
-
+ t_p = &ioloop->timeouts;
+ for (t = ioloop->timeouts; t != NULL; t = *t_p) {
if (t->destroyed) {
- timeout_destroy(ioloop, t);
+ timeout_destroy(ioloop, t_p);
continue;
}
+ t_p = &t->next;
if (!t->run_now) {
io_loop_get_wait_time(t, &tv, &ioloop_timeval);
(void *) io->callback, io->fd);
io_remove(io);
}
- io_destroy(ioloop, io);
+ io_destroy(ioloop, &ioloop->ios);
}
while (ioloop->timeouts != NULL) {
i_warning("Timeout leak: %p", (void *) to->callback);
timeout_remove(to);
}
- timeout_destroy(ioloop, to);
+ timeout_destroy(ioloop, &ioloop->timeouts);
}
io_loop_handler_deinit(ioloop);
#define IO_READ (1 << 0)
#define IO_WRITE (1 << 1)
-#define IO_PRIORITY_LOW 100
-#define IO_PRIORITY_DEFAULT 0
-#define IO_PRIORITY_HIGH -100
-
struct io;
struct timeout;
struct ioloop;
but make sure you don't create multiple handlers of same type, it's not
checked and removing one will stop the other from working as well. */
struct io *io_add(int fd, int condition, io_callback_t *callback, void *context);
-struct io *io_add_priority(int fd, int priority, int condition,
- io_callback_t *callback, void *context);
void io_remove(struct io *io);
/* Timeout handlers */
-struct timeout *timeout_add(int msecs, timeout_callback_t *callback,
+struct timeout *timeout_add(unsigned int msecs, timeout_callback_t *callback,
void *context);
void timeout_remove(struct timeout *timeout);
struct _ostream ostream;
int fd;
- int priority;
struct io *io;
unsigned char *buffer; /* ring-buffer */
if (sent != 0 && fstream->io == NULL &&
!fstream->corked && !fstream->file) {
- fstream->io = io_add_priority(fstream->fd, fstream->priority,
- IO_WRITE, stream_send_io,
- fstream);
+ fstream->io = io_add(fstream->fd, IO_WRITE, stream_send_io,
+ fstream);
}
i_assert(!STREAM_IS_BLOCKING(fstream) || sent == size);
struct ostream *
o_stream_create_file(int fd, pool_t pool, size_t max_buffer_size,
- int priority, int autoclose_fd)
+ int autoclose_fd)
{
struct file_ostream *fstream;
struct ostream *ostream;
fstream = p_new(pool, struct file_ostream, 1);
fstream->fd = fd;
- fstream->priority = priority;
fstream->max_buffer_size = max_buffer_size;
fstream->autoclose_fd = autoclose_fd;
fstream->optimal_block_size = DEFAULT_OPTIMAL_BLOCK_SIZE;
struct ostream *
o_stream_create_file(int fd, pool_t pool, size_t max_buffer_size,
- int priority, int autoclose_fd);
+ int autoclose_fd);
/* Reference counting. References start from 1, so calling o_stream_unref()
destroys the stream if o_stream_ref() is never used. */
conn->input = i_stream_create_file(fd, default_pool, MAX_INBUF_SIZE,
FALSE);
conn->output = o_stream_create_file(fd, default_pool, MAX_OUTBUF_SIZE,
- IO_PRIORITY_DEFAULT, FALSE);
+ FALSE);
conn->requests = hash_create(default_pool, default_pool, 100,
NULL, NULL);
MAX_INBUF_SIZE, FALSE);
p->output = o_stream_create_file(fd, default_pool,
sizeof(struct auth_master_request)*100,
- IO_PRIORITY_DEFAULT, FALSE);
+ FALSE);
p->requests = hash_create(default_pool, default_pool, 0, NULL, NULL);
p->next = group->processes;
p->io = io_add(fd, IO_READ, login_process_input, p);
p->output = o_stream_create_file(fd, default_pool,
sizeof(struct master_login_reply)*10,
- IO_PRIORITY_DEFAULT, FALSE);
+ FALSE);
PID_ADD_PROCESS_TYPE(pid, PROCESS_TYPE_LOGIN);
hash_insert(processes, POINTER_CAST(pid), p);
#include "common.h"
#include "ssl-init.h"
+#if 0
#ifdef HAVE_OPENSSL
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+static int rsa_bits[] = { 512, 1024, 0 };
+static int dh_bits[] = { 768, 1024, 0 };
+
+static const char *ssl_last_error(void)
+{
+ unsigned long err;
+ char *buf;
+ size_t err_size = 256;
+
+ err = ERR_get_error();
+ if (err == 0)
+ return strerror(errno);
+
+ buf = t_malloc(err_size);
+ buf[err_size-1] = '\0';
+ ERR_error_string_n(err, buf, err_size-1);
+ return buf;
+}
+
+static void write_datum(int fd, const char *fname, gnutls_datum *dbits)
+{
+ if (write_full(fd, &dbits->size, sizeof(dbits->size)) < 0)
+ i_fatal("write_full() failed for file %s: %m", fname);
+
+ if (write_full(fd, dbits->data, dbits->size) < 0)
+ i_fatal("write_full() failed for file %s: %m", fname);
+}
+
+static void generate_dh_parameters(int fd, const char *fname)
+{
+ gnutls_datum dbits, prime, generator;
+ int ret, bits, i;
+
+ dbits.size = sizeof(bits);
+ dbits.data = (unsigned char *) &bits;
+
+ for (i = 0; dh_bits[i] != 0; i++) {
+ bits = dh_bits[i];
+
+ ret = gnutls_dh_params_generate(&prime, &generator, bits);
+ if (ret < 0) {
+ i_fatal("gnutls_dh_params_generate(%d) failed: %s",
+ bits, gnutls_strerror(ret));
+ }
+
+ write_datum(fd, fname, &dbits);
+ write_datum(fd, fname, &prime);
+ write_datum(fd, fname, &generator);
+
+ free(prime.data);
+ free(generator.data);
+ }
+
+ bits = 0;
+ write_datum(fd, fname, &dbits);
+}
+
+static void generate_rsa_parameters(int fd, const char *fname)
+{
+ RSA *rsa;
+ int ret;
+
+ for (i = 0; rsa_bits[i] != 0; i++) {
+ rsa = RSA_generate_key(rsa_bits[i], RSA_F4, NULL, NULL);
+ if (rsa == NULL) {
+ i_fatal("RSA_generate_keys(%d bits) failed: %s",
+ rsa_bits[i], ssl_last_error());
+ }
+
+
+
+ RSA_free(rsa);
+ }
+
+ ret = gnutls_rsa_params_generate(&m, &e, &d, &p, &q, &u, 512);
+ if (ret < 0) {
+ i_fatal("gnutls_rsa_params_generate() faile: %s",
+ strerror(ret));
+ }
+
+ write_datum(fd, fname, &m);
+ write_datum(fd, fname, &e);
+ write_datum(fd, fname, &d);
+ write_datum(fd, fname, &p);
+ write_datum(fd, fname, &q);
+ write_datum(fd, fname, &u);
+}
+
+void _ssl_generate_parameters(int fd, const char *fname)
+{
+ SSL_CTX *ssl_ctx;
+
+ SSL_library_init();
+ SSL_load_error_strings();
+
+ if ((ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL)
+ i_fatal("SSL_CTX_new() failed");
+
+ generate_dh_parameters(fd, fname);
+ generate_rsa_parameters(fd, fname);
+
+ SSL_CTX_free(ssl_ctx);
+}
+
+struct ssl_key_cache {
+ RSA *key;
+ int keylength;
+};
+
+static RSA *ssl_gen_rsa_key(SSL *ssl __attr_unused__,
+ int is_export __attr_unused__, int keylength)
+{
+ static buffer_t *key_cache = NULL;
+ const struct ssl_key_cache *cache;
+ struct ssl_key_cache tmp_cache;
+ size_t i, size;
+
+ if (key_cache == NULL)
+ key_cache = buffer_create_dynamic(system_pool, 64, (size_t)-1);
+
+ cache = buffer_get_data(key_cache, &size);
+ size /= sizeof(struct ssl_key_cache);
+
+ for (i = 0; i < size; i++) {
+ if (cache[i].keylength == keylength)
+ return cache[i].key;
+ }
+
+ tmp_cache.key = RSA_generate_key(keylength, RSA_F4, NULL, NULL);
+ if (tmp_cache.key == NULL) {
+ i_error("Can't create temporary RSA key with length %d: %s",
+ keylength, ssl_last_error());
+ return NULL;
+ }
+ tmp_cache.keylength = keylength;
+ buffer_append(key_cache, &tmp_cache, sizeof(tmp_cache));
+
+ return tmp_cache.key;
+}
+
+#endif
+#else
void _ssl_generate_parameters(int fd __attr_unused__,
const char *fname __attr_unused__)
{
}
-
#endif
static void client_open_streams(struct pop3_client *client, int fd)
{
client->input = i_stream_create_file(fd, default_pool, 8192, FALSE);
- client->output = o_stream_create_file(fd, default_pool, 1024,
- IO_PRIORITY_DEFAULT, FALSE);
+ client->output = o_stream_create_file(fd, default_pool, 1024, FALSE);
}
static int cmd_stls(struct pop3_client *client)
client = i_new(struct client, 1);
client->input = i_stream_create_file(hin, default_pool,
MAX_INBUF_SIZE, FALSE);
- client->output = o_stream_create_file(hout, default_pool, 4096,
- IO_PRIORITY_DEFAULT, FALSE);
+ client->output = o_stream_create_file(hout, default_pool, 4096, FALSE);
/* set timeout for sending data */
o_stream_set_blocking(client->output, CLIENT_OUTPUT_TIMEOUT,