]> source.dussan.org Git - rspamd.git/commitdiff
Add universal utility function for creating stream sockets.
authorVsevolod Stakhov <vsevolod@rambler-co.ru>
Tue, 18 Oct 2011 14:56:51 +0000 (17:56 +0300)
committerVsevolod Stakhov <vsevolod@rambler-co.ru>
Tue, 18 Oct 2011 14:56:51 +0000 (17:56 +0300)
src/lmtp_proto.c
src/main.c
src/smtp_utils.c
src/util.c
src/util.h

index a8c462b03376cc69d73dc96343636509dfc46998..1ea64ddf4a2171f2e25f17757480e6990df13ad3 100644 (file)
@@ -452,7 +452,7 @@ lmtp_deliver_mta (struct worker_task *task)
 
        if (task->cfg->deliver_family == AF_UNIX) {
                un = alloca (sizeof (struct sockaddr_un));
-               sock = make_unix_socket (task->cfg->deliver_host, un, FALSE);
+               sock = make_unix_socket (task->cfg->deliver_host, un, FALSE, TRUE);
        }
        else {
                sock = make_tcp_socket (&task->cfg->deliver_addr, task->cfg->deliver_port, FALSE, TRUE);
index 25e9dd5628fa1de16b5d17891ecdf21f3dfed095..e470a1e8be76ba3ba827a296105d417a742738b0 100644 (file)
@@ -473,7 +473,7 @@ create_listen_socket (struct in_addr *addr, gint port, gint family, gchar *path)
        }
        else {
                un_addr = (struct sockaddr_un *)alloca (sizeof (struct sockaddr_un));
-               if (!un_addr || (listen_sock = make_unix_socket (path, un_addr, TRUE)) == -1) {
+               if (!un_addr || (listen_sock = make_unix_socket (path, un_addr, TRUE, TRUE)) == -1) {
                        msg_err ("cannot create unix listen socket. %s", strerror (errno));
                }
        }
index 27dffd275f115ac3927e4cda78c0d94d221604b1..1ed92ead6550f3b5010229863fd96e2c72385847 100644 (file)
@@ -78,7 +78,7 @@ create_smtp_upstream_connection (struct smtp_session *session)
        /* Now try to create socket */
        if (selected->is_unix) {
                un = alloca (sizeof (struct sockaddr_un));
-               session->upstream_sock = make_unix_socket (selected->name, un, FALSE);
+               session->upstream_sock = make_unix_socket (selected->name, un, FALSE, TRUE);
        }
        else {
                session->upstream_sock = make_tcp_socket (&selected->addr, selected->port, FALSE, TRUE);
index 01936474ebb33051bd01ba69228550291bbdd00e..3ddfe3b611fe33b961d2282d12045f6d22db3c62 100644 (file)
@@ -215,7 +215,7 @@ accept_from_socket (gint listen_sock, struct sockaddr *addr, socklen_t * len)
 }
 
 gint
-make_unix_socket (const gchar *path, struct sockaddr_un *addr, gboolean is_server)
+make_unix_socket (const gchar *path, struct sockaddr_un *addr, gboolean is_server, gboolean async)
 {
        gint                            fd, s_error, r, optlen, serrno, on = 1;
 
@@ -258,6 +258,20 @@ make_unix_socket (const gchar *path, struct sockaddr_un *addr, gboolean is_serve
                        msg_warn ("bind/connect failed: %d, '%s'", errno, strerror (errno));
                        goto out;
                }
+               if (!async) {
+                       /* Try to poll */
+                       if (poll_sync_socket (fd, CONNECT_TIMEOUT * 1000, POLLOUT) <= 0) {
+                               errno = ETIMEDOUT;
+                               msg_warn ("bind/connect failed: timeout");
+                               goto out;
+                       }
+                       else {
+                               /* Make synced again */
+                               if (make_socket_blocking (fd) < 0) {
+                                       goto out;
+                               }
+                       }
+               }
        }
        else {
                /* Still need to check SO_ERROR on socket */
@@ -279,6 +293,78 @@ make_unix_socket (const gchar *path, struct sockaddr_un *addr, gboolean is_serve
        return (-1);
 }
 
+/**
+ * Make universal stream socket
+ * @param credits host, ip or path to unix socket
+ * @param port port (used for network sockets)
+ * @param async make this socket asynced
+ * @param is_server make this socket as server socket
+ * @param try_resolve try name resolution for a socket (BLOCKING)
+ */
+gint
+make_universal_stream_socket (const gchar *credits, guint16 port, gboolean async, gboolean is_server, gboolean try_resolve)
+{
+       struct sockaddr_un              un;
+       struct stat                     st;
+       struct in_addr                  in;
+       struct hostent                             *he;
+       gint                            r;
+
+       if (*credits == '/') {
+               r = stat (credits, &st);
+               if (is_server) {
+                       if (r == -1) {
+                               return make_unix_socket (credits, &un, is_server, async);
+                       }
+                       else {
+                               /* Unix socket exists, it must be unlinked first */
+                               errno = EEXIST;
+                               return -1;
+                       }
+               }
+               else {
+                       if (r == -1) {
+                               /* Unix socket doesn't exists it must be created first */
+                               errno = ENOENT;
+                               return -1;
+                       }
+                       else {
+                               if ((st.st_mode & S_IFSOCK) == 0) {
+                                       /* Path is not valid socket */
+                                       errno = EINVAL;
+                                       return -1;
+                               }
+                               else {
+                                       return make_unix_socket (credits, &un, is_server, async);
+                               }
+                       }
+               }
+       }
+       else {
+               /* TCP related part */
+               if (inet_aton (credits, &in) == 0) {
+                       /* Try to resolve */
+                       if (try_resolve) {
+                               if ((he = gethostbyname (credits)) == NULL) {
+                                       errno = ENOENT;
+                                       return -1;
+                               }
+                               else {
+                                       memcpy (&in, he->h_addr, sizeof (struct in_addr));
+                                       return make_tcp_socket (&in, port, is_server, async);
+                               }
+                       }
+                       else {
+                               errno = ENOENT;
+                               return -1;
+                       }
+               }
+               else {
+                       return make_tcp_socket (&in, port, is_server, async);
+               }
+       }
+}
+
 gint
 make_socketpair (gint pair[2])
 {
index 7a5a00915c26fe865b743e73bb89d7c7f5d4b2fa..7bdf3bdc45c0403eea2aa23d55b74d56d4674b79 100644 (file)
@@ -44,7 +44,18 @@ gint accept_from_socket (gint listen_sock, struct sockaddr *addr, socklen_t *len
 /*
  * Create and bind or connect unix socket
  */
-gint make_unix_socket (const gchar *, struct sockaddr_un *, gboolean is_server);
+gint make_unix_socket (const gchar *, struct sockaddr_un *, gboolean is_server, gboolean async);
+
+/**
+ * Make universal stream socket
+ * @param credits host, ip or path to unix socket
+ * @param port port (used for network sockets)
+ * @param async make this socket asynced
+ * @param is_server make this socket as server socket
+ * @param try_resolve try name resolution for a socket (BLOCKING)
+ */
+gint make_universal_stream_socket (const gchar *credits, guint16 port,
+               gboolean async, gboolean is_server, gboolean try_resolve);
 
 /*
  * Create socketpair