Change to using enums for g_socket_new
[cascardo/gnio.git] / gnio / gsocket.c
index eeb848e..f9410bf 100644 (file)
@@ -158,16 +158,74 @@ g_socket_init (GSocket *socket)
 }
 
 GSocket *
-g_socket_new (gint domain, gint type, gint protocol)
+g_socket_new (GSocketDomain domain, GSocketType type, const gchar *protocol, GError **error)
 {
-  gint sock;
+  static GStaticMutex getprotobyname_mutex = G_STATIC_MUTEX_INIT;
+  gint fd, native_domain, native_type, native_protocol;
 
-  sock = socket(domain, type, protocol);
+  switch (domain)
+    {
+      case G_SOCKET_DOMAIN_INET:
+        native_domain = PF_INET;
+        break;
 
-  if (sock < 0)
-    return NULL;
+      case G_SOCKET_DOMAIN_INET6:
+        native_domain = PF_INET6;
+        break;
+
+      case G_SOCKET_DOMAIN_UNIX:
+        native_domain = PF_UNIX;
+        break;
+
+      default:
+        g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "unsupported socket domain");
+        return NULL;
+    }
+
+  switch (type)
+    {
+      case G_SOCKET_TYPE_STREAM:
+        native_type = SOCK_STREAM;
+        break;
+
+      case G_SOCKET_TYPE_DATAGRAM:
+        native_type = SOCK_DGRAM;
+        break;
+
+      case G_SOCKET_TYPE_SEQPACKET:
+        native_type = SOCK_SEQPACKET;
+        break;
 
-  return G_SOCKET (g_object_new (G_TYPE_SOCKET, "fd", sock, NULL));
+      default:
+        g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "unsupported socket type");
+        return NULL;
+    }
+
+  if (protocol == NULL)
+    native_protocol = 0;
+  else
+    {
+      struct protoent *ent;
+      g_static_mutex_lock (&getprotobyname_mutex);
+      if (!(ent = getprotobyname (protocol)))
+        {
+          g_static_mutex_unlock (&getprotobyname_mutex);
+          g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "unsupported socket protocol");
+          return NULL;
+        }
+      native_protocol = ent->p_proto;
+      g_static_mutex_unlock (&getprotobyname_mutex);
+    }
+
+  fd = socket(native_domain, native_type, native_protocol);
+
+  if (fd < 0)
+    {
+      g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "unable to create socket: %s", g_strerror (errno));
+      return NULL;
+    }
+
+  return G_SOCKET (g_object_new (G_TYPE_SOCKET, "fd", fd, NULL));
 }
 
 GSocket *
@@ -222,7 +280,7 @@ g_socket_get_peer_address (GSocket  *socket,
 
   if (getpeername (socket->priv->fd, (struct sockaddr *) buffer, &len) < 0)
     {
-      g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "could not get peer address");
+      g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "could not get peer address: %s", g_strerror (errno));
       return NULL;
     }
 
@@ -253,7 +311,7 @@ g_socket_bind (GSocket         *socket,
 
     if (bind (socket->priv->fd, (struct sockaddr *) addr, g_socket_address_native_size (address)) < 0)
       {
-        // TODO: set error
+        g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "error binding to address: %s", g_strerror (errno));
         return FALSE;
       }
 
@@ -321,6 +379,7 @@ accept_callback (AcceptData *data,
 
           g_simple_async_result_set_op_res_gpointer (result, g_socket_new_from_fd (ret), g_object_unref);
         }
+
       g_simple_async_result_complete (result);
 
       g_object_unref (result);