⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 conn.c

📁 The Kannel Open Source WAP and SMS gateway works as both an SMS gateway, for implementing keyword b
💻 C
📖 第 1 页 / 共 3 页
字号:
  return conn_open_tcp_nb_with_port(host, port, 0, our_host);}Connection *conn_open_tcp_nb_with_port(Octstr *host, int port, int our_port,				       Octstr *our_host){  int sockfd;  int done = -1;  Connection *c;  sockfd = tcpip_connect_nb_to_server_with_port(octstr_get_cstr(host), port,						our_port, our_host == NULL ?						NULL : octstr_get_cstr(our_host), &done);  if (sockfd < 0)    return NULL;  c = conn_wrap_fd(sockfd, 0);  if (done != 0) {    c->connected = no;  }  return c;}int conn_is_connected(Connection *conn){  if (conn->connected == yes) return 0;  return -1;}int conn_get_connect_result(Connection *conn){  int err,len;  len = sizeof(len);  if (getsockopt(conn->fd, SOL_SOCKET, SO_ERROR, &err, &len) < 0) {    return -1;  }    if (err) {    return -1;  }    conn->connected = yes;  return 0;}Connection *conn_open_tcp_with_port(Octstr *host, int port, int our_port,		Octstr *our_host){    int sockfd;    sockfd = tcpip_connect_to_server_with_port(octstr_get_cstr(host), port,					       our_port, our_host == NULL ?					       NULL : octstr_get_cstr(our_host));    if (sockfd < 0)	return NULL;    return conn_wrap_fd(sockfd, 0);}Connection *conn_wrap_fd(int fd, int ssl){    Connection *conn;    if (socket_set_blocking(fd, 0) < 0)        return NULL;    conn = gw_malloc(sizeof(*conn));    conn->inlock = mutex_create();    conn->outlock = mutex_create();    conn->claimed = 0;    conn->outbuf = octstr_create("");    conn->outbufpos = 0;    conn->inbuf = octstr_create("");    conn->inbufpos = 0;    conn->fd = fd;    conn->connected = yes;    conn->read_eof = 0;    conn->io_error = 0;    conn->output_buffering = DEFAULT_OUTPUT_BUFFERING;    conn->registered = NULL;    conn->callback = NULL;    conn->callback_data = NULL;    conn->listening_pollin = 0;    conn->listening_pollout = 0;#ifdef HAVE_LIBSSL    /*     * do all the SSL magic for this connection     */    if (ssl) {        conn->ssl = SSL_new(global_server_ssl_context);        conn->peer_certificate = NULL;        /* SSL_set_fd can fail, so check it */        if (SSL_set_fd(conn->ssl, conn->fd) == 0) {            /* SSL_set_fd failed, log error and return NULL */            error(errno, "SSL: OpenSSL: %.256s", ERR_error_string(ERR_get_error(), NULL));            conn_destroy(conn);            return NULL;        }        /* SSL_set_verify(conn->ssl, 0, NULL); */        /* set read/write BIO layer to non-blocking mode */        BIO_set_nbio(SSL_get_rbio(conn->ssl), 1);        BIO_set_nbio(SSL_get_wbio(conn->ssl), 1);        /* set accept state , SSL-Handshake will be handled transparent while SSL_[read|write] */         SSL_set_accept_state(conn->ssl);    } else {        conn->ssl = NULL;        conn->peer_certificate = NULL;    }#endif /* HAVE_LIBSSL */    return conn;}void conn_destroy(Connection *conn){    int ret;    if (conn == NULL)        return;    /* No locking done here.  conn_destroy should not be called     * if any thread might still be interested in the connection. */    if (conn->registered)        fdset_unregister(conn->registered, conn->fd);    if (conn->fd >= 0) {        /* Try to flush any remaining data */        unlocked_try_write(conn);#ifdef HAVE_LIBSSL        if (conn->ssl != NULL) {            SSL_smart_shutdown(conn->ssl);            SSL_free(conn->ssl);            if (conn->peer_certificate != NULL)                X509_free(conn->peer_certificate);	}#endif /* HAVE_LIBSSL */        ret = close(conn->fd);        if (ret < 0)            error(errno, "conn_destroy: error on close");        conn->fd = -1;    }    octstr_destroy(conn->outbuf);    octstr_destroy(conn->inbuf);    mutex_destroy(conn->inlock);    mutex_destroy(conn->outlock);    gw_free(conn);}void conn_claim(Connection *conn){    gw_assert(conn != NULL);    if (conn->claimed)        panic(0, "Connection is being claimed twice!");    conn->claimed = 1;#ifndef NO_GWASSERT    conn->claiming_thread = gwthread_self();#endif}long conn_outbuf_len(Connection *conn){    long len;    lock_out(conn);    len = unlocked_outbuf_len(conn);    unlock_out(conn);    return len;}long conn_inbuf_len(Connection *conn){    long len;    lock_in(conn);    len = unlocked_inbuf_len(conn);    unlock_in(conn);    return len;}int conn_eof(Connection *conn){    int eof;    lock_in(conn);    eof = conn->read_eof;    unlock_in(conn);    return eof;}int conn_error(Connection *conn){    int err;    lock_in(conn);    lock_out(conn);    err = conn->io_error;    unlock_in(conn);    unlock_out(conn);    return err;}void conn_set_output_buffering(Connection *conn, unsigned int size){    lock_out(conn);    conn->output_buffering = size;    /* If the buffer size is smaller, we may have to write immediately. */    unlocked_try_write(conn);    unlock_out(conn);}static void poll_callback(int fd, int revents, void *data){    Connection *conn;    int do_callback = 0;    conn = data;    if (conn == NULL) {        error(0, "poll_callback called with NULL connection.");        return;    }    if (conn->fd != fd) {        error(0, "poll_callback called on wrong connection.");        return;    }    /* Get result of nonblocking connect, before any reads and writes     * we must check result (it must be handled in initial callback) */    if (conn->connected == no) {        if (conn->callback)            conn->callback(conn, conn->callback_data);        return;    }    /* If got POLLERR or POLHUP, then unregister the descriptor from the     * fdset and set the error condition variable to let the upper layer     * close and destroy the connection. */    if (revents & (POLLERR|POLLHUP)) {        lock_in(conn);        lock_out(conn);        if (conn->listening_pollin)            unlocked_register_pollin(conn, 0);        if (conn->listening_pollout)            unlocked_register_pollout(conn, 0);        conn->io_error = 1;        unlock_in(conn);        unlock_out(conn);        do_callback = 1;    }    /* If unlocked_write manages to write all pending data, it will     * tell the fdset to stop listening for POLLOUT. */    if (revents & POLLOUT) {        lock_out(conn);        unlocked_write(conn);        if (unlocked_outbuf_len(conn) == 0)            do_callback = 1;        unlock_out(conn);    }    /* We read only in unlocked_read in we received POLLIN, cause the      * descriptor is already broken and of no use anymore. */    if (revents & POLLIN) {        lock_in(conn);        unlocked_read(conn);        unlock_in(conn);        do_callback = 1;    }    if (do_callback && conn->callback)        conn->callback(conn, conn->callback_data);}int conn_register(Connection *conn, FDSet *fdset,                  conn_callback_t callback, void *data){    int events;    int result = 0;    gw_assert(conn != NULL);    if (conn->fd < 0)        return -1;    /* We need both locks if we want to update the registration     * information. */    lock_out(conn);    lock_in(conn);    if (conn->registered == fdset) {        /* Re-registering.  Change only the callback info. */        conn->callback = callback;        conn->callback_data = data;        result = 0;    } else if (conn->registered) {        /* Already registered to a different fdset. */        result = -1;    } else {        events = 0;	/* For nonconnected socket we must lesten both directions */        if (conn->connected == yes) {            if (conn->read_eof == 0 && conn->io_error == 0)                events |= POLLIN;            if (unlocked_outbuf_len(conn) > 0)                events |= POLLOUT;        } else {          events |= POLLIN | POLLOUT;        }        conn->registered = fdset;        conn->callback = callback;        conn->callback_data = data;        conn->listening_pollin = (events & POLLIN) != 0;        conn->listening_pollout = (events & POLLOUT) != 0;        fdset_register(fdset, conn->fd, events, poll_callback, conn);        result = 0;    }    unlock_out(conn);    unlock_in(conn);    return result;}void conn_unregister(Connection *conn){    gw_assert(conn != NULL);    if (conn->fd < 0)        return;    /* We need both locks to update the registration information */    lock_out(conn);    lock_in(conn);    if (conn->registered) {        fdset_unregister(conn->registered, conn->fd);        conn->registered = NULL;        conn->callback = NULL;        conn->callback_data = NULL;        conn->listening_pollin = 0;        conn->listening_pollout = 0;    }    unlock_in(conn);    unlock_out(conn);}int conn_wait(Connection *conn, double seconds){    int events;    int ret;    int fd;    lock_out(conn);    /* Try to write any data that might still be waiting to be sent */    ret = unlocked_write(conn);    if (ret < 0) {        unlock_out(conn);        return -1;    }    if (ret > 0) {        /* We did something useful.  No need to poll or wait now. */        unlock_out(conn);        return 0;    }    fd = conn->fd;    /* Normally, we block until there is more data available.  But     * if any data still needs to be sent, we block until we can     * send it (or there is more data available).  We always block     * for reading, unless we know there is no more data coming.     * (Because in that case, poll will keep reporting POLLIN to     * signal the end of the file).  If the caller explicitly wants     * to wait even though there is no data to write and we're at     * end of file, then poll for new data anyway because the caller     * apparently doesn't trust eof. */    events = 0;    if (unlocked_outbuf_len(conn) > 0)        events |= POLLOUT;    /* Don't keep the connection locked while we wait */    unlock_out(conn);    /* We need the in lock to query read_eof */    lock_in(conn);    if ((conn->read_eof == 0 && conn->io_error == 0) || events == 0)        events |= POLLIN;    unlock_in(conn);    ret = gwthread_pollfd(fd, events, seconds);    if (ret < 0) {        if (errno == EINTR)            return 0;        error(0, "conn_wait: poll failed on fd %d:", fd);        return -1;    }    if (ret == 0)        return 1;    if (ret & POLLNVAL) {        error(0, "conn_wait: fd %d not open.", fd);        return -1;    }    if (ret & (POLLERR | POLLHUP)) {        /* Call unlocked_read to report the specific error,         * and handle the results of the error.  We can't be         * certain that the error still exists, because we         * released the lock for a while. */        lock_in(conn);        unlocked_read(conn);        unlock_in(conn);        return -1;    }    /* If POLLOUT is on, then we must have wanted     * to write something. */    if (ret & POLLOUT) {        lock_out(conn);        unlocked_write(conn);        unlock_out(conn);    }    /* Since we normally select for reading, we must     * try to read here.  Otherwise, if the caller loops     * around conn_wait without making conn_read* calls     * in between, we will keep polling this same data. */    if (ret & POLLIN) {        lock_in(conn);        unlocked_read(conn);        unlock_in(conn);    }    return 0;}int conn_flush(Connection *conn){    int ret;    int revents;    int fd;    lock_out(conn);    ret = unlocked_write(conn);    if (ret < 0) {        unlock_out(conn);        return -1;    }    while (unlocked_outbuf_len(conn) != 0) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -