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);
/* 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);
}
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;
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 */
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])
{
/*
* 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