Skip to content

Instantly share code, notes, and snippets.

@jimblandy
Created May 1, 2013 19:02
Show Gist options
  • Save jimblandy/5497508 to your computer and use it in GitHub Desktop.
Save jimblandy/5497508 to your computer and use it in GitHub Desktop.
Add support for Unix-domain sockets to nsIServerSocket.idl and @mozilla.org/network/server-socket;1.
diff --git a/netwerk/base/public/nsIServerSocket.idl b/netwerk/base/public/nsIServerSocket.idl
--- a/netwerk/base/public/nsIServerSocket.idl
+++ b/netwerk/base/public/nsIServerSocket.idl
@@ -95,6 +95,54 @@ interface nsIServerSocket : nsISupports
[noscript] void initWithAddress([const] in PRNetAddrPtr aAddr, in long aBackLog);
/**
+ * initWithFilename
+ *
+ * This method initializes a Unix-domain or "local" server socket. Such
+ * a socket has a name in the filesystem, like an ordinary file. To
+ * connect, a client supplies the socket's filename, and the usual
+ * permission checks on socket apply.
+ *
+ * This makes Unix-domain sockets useful for communication between the
+ * programs a specific user on a single machine: the operating system
+ * takes care of authentication, and the user's home directory or
+ * profile directory provide natural per-user rendezvous points.
+ *
+ * This call requires execute permission on all directories containing
+ * the one in which the socket is to be created, and write and execute
+ * permission on the directory itself. Otherwise, this returns
+ * NS_ERROR_FILE_ACCESS_DENIED.
+ *
+ * This call creates the socket's directory entry. There must not
+ * be any existing file, directory, or socket with the given name. If
+ * there is, this returns NS_ERROR_FILE_ALREADY_EXISTS.
+ *
+ * The directory in which the socket is to be created must already
+ * exist. Otherwise, this returns NS_ERROR_FILE_NOT_FOUND.
+ *
+ * The system-level socket API may impose restrictions on the length of
+ * the filename that are stricter than those of the underlying
+ * filesystem. If the file name is too long, this returns
+ * NS_ERROR_FILE_NAME_TOO_LONG.
+ *
+ * @param aPath nsIFile
+ * The file name at which the socket should be created.
+ *
+ * @param aPermissions unsigned long
+ * Unix-style permission bits to be applied to the new socket.
+ *
+ * Note about permissions: Linux's unix(7) man page claims that some
+ * BSD-derived systems ignore permissions on UNIX-domain sockets;
+ * NetBSD's bind(2) man page agrees, but says it does check now (dated
+ * 2005). POSIX has required 'connect' to fail if write permission on
+ * the socket itself is not granted since 2003 (Issue 6). NetBSD says
+ * that the permissions on the containing directory (execute) have
+ * always applied, so creating sockets in appropriately protected
+ * directories should be secure on both old and new systems.
+ */
+ void initWithFilename(in nsIFile aPath, in unsigned long aPermissions,
+ in long aBacklog);
+
+ /**
* close
*
* This method closes a server socket. This does not affect already
diff --git a/netwerk/base/src/nsServerSocket.cpp b/netwerk/base/src/nsServerSocket.cpp
--- a/netwerk/base/src/nsServerSocket.cpp
+++ b/netwerk/base/src/nsServerSocket.cpp
@@ -258,6 +258,26 @@ nsServerSocket::Init(int32_t aPort, bool
}
NS_IMETHODIMP
+nsServerSocket::InitWithFilename(nsIFile aPath, unsigned long aPermissions, int32_t aBacklog)
+{
+ nsresult rv;
+
+ nsAutoCString path;
+ rv = aPath->GetNativePath(aPath);
+ if (NS_FAILED(rv)) return rv;
+
+ // Create a Unix-domain PRNetAddr referring to the given path.
+ PRNetAddr addr;
+ if (path.Length() + 1 > sizeof(addr.local.path))
+ return NS_ERROR_FILE_NAME_TOO_LONG;
+ addr.local.family = AF_UNIX;
+ memcpy(addr.local.path, path.get(), path.Length());
+ addr.local.path[path.Length()] = '\0';
+
+ return InitWithAddress(&addr, aBacklog);
+}
+
+NS_IMETHODIMP
nsServerSocket::InitSpecialConnection(int32_t aPort, nsServerSocketFlag aFlags,
int32_t aBackLog)
{
diff --git a/xpcom/io/nsIFile.idl b/xpcom/io/nsIFile.idl
--- a/xpcom/io/nsIFile.idl
+++ b/xpcom/io/nsIFile.idl
@@ -18,9 +18,21 @@
interface nsISimpleEnumerator;
/**
- * This is the only correct cross-platform way to specify a file.
- * Strings are not such a way. If you grew up on windows or unix, you
- * may think they are. Welcome to reality.
+ * An nsIFile is an abstract representation of a filename. It manages
+ * filename encoding issues, pathname components separators ('/' vs. '\\'
+ * vs. ':') and weird stuff like differing volumes with identical names, as
+ * on pre-Darwin Macintoshes.
+ *
+ * This file has long introduced itself to new hackers with this opening
+ * paragraph:
+ *
+ * This is the only correct cross-platform way to specify a file.
+ * Strings are not such a way. If you grew up on windows or unix, you
+ * may think they are. Welcome to reality.
+ *
+ * While taking the attitude here at face value would be uncalled for, one
+ * may still safely conclude that writing cross-platform code is an
+ * embittering experience.
*
* All methods with string parameters have two forms. The preferred
* form operates on UCS-2 encoded characters strings. An alternate
@@ -28,7 +40,7 @@ interface nsISimpleEnumerator;
*
* A string containing characters encoded in the native charset cannot
* be safely passed to javascript via xpconnect. Therefore, the "native
- * methods" are not scriptable.
+ * methods" are not scriptable.
*/
[scriptable, uuid(272a5020-64f5-485c-a8c4-44b2882ae0a2), builtinclass]
interface nsIFile : nsISupports
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment