aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/library.js88
-rw-r--r--tests/sockets/test_getprotobyname.c87
-rw-r--r--tests/test_sockets.py3
3 files changed, 178 insertions, 0 deletions
diff --git a/src/library.js b/src/library.js
index 1e8c6ba6..bdc0a39e 100644
--- a/src/library.js
+++ b/src/library.js
@@ -7701,6 +7701,94 @@ LibraryManager.library = {
return _gai_strerror.buffer;
},
+ // Implement netdb.h protocol entry (getprotoent, getprotobyname, getprotobynumber, setprotoent, endprotoent)
+ // http://pubs.opengroup.org/onlinepubs/9699919799/functions/getprotobyname.html
+ // The Protocols object holds our 'fake' protocols 'database'.
+ $Protocols: {
+ list: [],
+ map: {}
+ },
+ setprotoent__deps: ['$Protocols'],
+ setprotoent: function(stayopen) {
+ // void setprotoent(int stayopen);
+
+ // Allocate and populate a protoent structure given a name, protocol number and array of aliases
+ function allocprotoent(name, proto, aliases) {
+ // write name into buffer
+ var nameBuf = _malloc(name.length + 1);
+ writeAsciiToMemory(name, nameBuf);
+
+ // write aliases into buffer
+ var j = 0;
+ var length = aliases.length;
+ var aliasListBuf = _malloc((length + 1) * 4); // Use length + 1 so we have space for the terminating NULL ptr.
+
+ for (var i = 0; i < length; i++, j += 4) {
+ var alias = aliases[i];
+ var aliasBuf = _malloc(alias.length + 1);
+ writeAsciiToMemory(alias, aliasBuf);
+ {{{ makeSetValue('aliasListBuf', 'j', 'aliasBuf', 'i8*') }}};
+ }
+ {{{ makeSetValue('aliasListBuf', 'j', '0', 'i8*') }}}; // Terminating NULL pointer.
+
+ // generate protoent
+ var pe = _malloc({{{ C_STRUCTS.protoent.__size__ }}});
+ {{{ makeSetValue('pe', C_STRUCTS.protoent.p_name, 'nameBuf', 'i8*') }}};
+ {{{ makeSetValue('pe', C_STRUCTS.protoent.p_aliases, 'aliasListBuf', 'i8**') }}};
+ {{{ makeSetValue('pe', C_STRUCTS.protoent.p_proto, 'proto', 'i32') }}};
+ return pe;
+ };
+
+ // Populate the protocol 'database'. The entries are limited to tcp and udp, though it is fairly trivial
+ // to add extra entries from /etc/protocols if desired - though not sure if that'd actually be useful.
+ var list = Protocols.list;
+ var map = Protocols.map;
+ if (list.length === 0) {
+ var entry = allocprotoent('tcp', 6, ['TCP']);
+ list.push(entry);
+ map['tcp'] = map['6'] = entry;
+ entry = allocprotoent('udp', 17, ['UDP']);
+ list.push(entry);
+ map['udp'] = map['17'] = entry;
+ }
+
+ _setprotoent.index = 0;
+ },
+
+ endprotoent: function() {
+ // void endprotoent(void);
+ // We're not using a real protocol database so we don't do a real close.
+ },
+
+ getprotoent__deps: ['setprotoent', '$Protocols'],
+ getprotoent: function(number) {
+ // struct protoent *getprotoent(void);
+ // reads the next entry from the protocols 'database' or return NULL if 'eof'
+ if (_setprotoent.index === Protocols.list.length) {
+ return 0;
+ } else {
+ var result = Protocols.list[_setprotoent.index++];
+ return result;
+ }
+ },
+
+ getprotobyname__deps: ['setprotoent', '$Protocols'],
+ getprotobyname: function(name) {
+ // struct protoent *getprotobyname(const char *);
+ name = Pointer_stringify(name);
+ _setprotoent(true);
+ var result = Protocols.map[name];
+ return result;
+ },
+
+ getprotobynumber__deps: ['setprotoent', '$Protocols'],
+ getprotobynumber: function(number) {
+ // struct protoent *getprotobynumber(int proto);
+ _setprotoent(true);
+ var result = Protocols.map[number];
+ return result;
+ },
+
// ==========================================================================
// sockets. Note that the implementation assumes all sockets are always
// nonblocking
diff --git a/tests/sockets/test_getprotobyname.c b/tests/sockets/test_getprotobyname.c
new file mode 100644
index 00000000..571a287e
--- /dev/null
+++ b/tests/sockets/test_getprotobyname.c
@@ -0,0 +1,87 @@
+#include <assert.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+void checkEntryByValue(char* name, int port, char** aliasArray) {
+ struct protoent* entry;
+ char** aliases;
+
+ // Perform a protocol look up by name
+ entry = getprotobyname(name);
+ assert(entry != NULL);
+
+ // Check results
+ assert(strcmp(name, entry->p_name) == 0);
+ assert(port == entry->p_proto);
+
+ aliases = entry->p_aliases;
+ for (int i = 0; aliases[i] != NULL; i++) {
+ assert(strcmp(aliases[i], aliasArray[i]) == 0);
+ }
+
+ // Perform a protocol look up by number
+ entry = getprotobynumber(port);
+ assert(entry != NULL);
+
+ // Check results
+ assert(strcmp(name, entry->p_name) == 0);
+ assert(port == entry->p_proto);
+
+ aliases = entry->p_aliases;
+ for (int i = 0; aliases[i] != NULL; i++) {
+ assert(strcmp(aliases[i], aliasArray[i]) == 0);
+ }
+}
+
+void checkEntryDatabase() {
+ struct protoent* entry;
+
+ // Don't call setprotoent() initially as getprotoent() should open the "database" if necessary.
+ entry = getprotoent();
+ assert(entry != NULL);
+ assert(strcmp("tcp", entry->p_name) == 0);
+
+ entry = getprotoent();
+ assert(entry != NULL);
+ assert(strcmp("udp", entry->p_name) == 0);
+
+ // Check that setprotoent() correctly sets the next entry to the first entry
+ setprotoent(1);
+
+ entry = getprotoent();
+ assert(entry != NULL);
+ assert(strcmp("tcp", entry->p_name) == 0);
+
+ entry = getprotoent();
+ assert(entry != NULL);
+ assert(strcmp("udp", entry->p_name) == 0);
+
+ // If we do a getprotoent() that goes past the end of the 'database' check that it returns NULL.
+ entry = getprotoent();
+ assert(entry == NULL);
+}
+
+int main() {
+ // First check getprotobyname() and getprotobynumber()
+ char* aliases[] = {"TCP"};
+ checkEntryByValue("tcp", 6, aliases);
+
+ aliases[0] = "UDP";
+ checkEntryByValue("udp", 17, aliases);
+
+ // Check that the doomsday protocol hasn't been implemented :-) ......
+ assert(getprotobyname("doomsday") == NULL);
+
+ // Now check setprotoent() and getprotoent()
+ checkEntryDatabase();
+
+ endprotoent();
+
+ puts("success");
+
+ return EXIT_SUCCESS;
+}
+
diff --git a/tests/test_sockets.py b/tests/test_sockets.py
index 1229aa70..f9dcbc68 100644
--- a/tests/test_sockets.py
+++ b/tests/test_sockets.py
@@ -228,6 +228,9 @@ class sockets(BrowserCore):
def test_gethostbyname(self):
self.do_run(open(path_from_root('tests', 'sockets', 'test_gethostbyname.c')).read(), 'success')
+ def test_getprotobyname(self):
+ self.do_run(open(path_from_root('tests', 'sockets', 'test_getprotobyname.c')).read(), 'success')
+
def test_sockets_echo(self):
sockets_include = '-I'+path_from_root('tests', 'sockets')