Merging trunk into new-json branch to keep the branch in sync with trunk new-json
authorerickson <erickson@9efc2488-bf62-4759-914b-345cdb29e865>
Wed, 13 Jun 2007 14:03:35 +0000 (14:03 +0000)
committererickson <erickson@9efc2488-bf62-4759-914b-345cdb29e865>
Wed, 13 Jun 2007 14:03:35 +0000 (14:03 +0000)
$ svn merge -r 887:HEAD svn://svn.open-ils.org/OpenSRF/trunk
revision 887 is the changeset for the creation of the new-json branch
this is the first sync merge

git-svn-id: svn://svn.open-ils.org/OpenSRF/branches/new-json@946 9efc2488-bf62-4759-914b-345cdb29e865

58 files changed:
Makefile [new file with mode: 0644]
examples/srfsh_config.xsd [new file with mode: 0644]
install.conf [new file with mode: 0644]
src/Makefile
src/java/Makefile
src/java/ext/stax-api-1.0.1.jar [deleted file]
src/java/ext/wstx-asl-3.2.1.jar [deleted file]
src/java/org/opensrf/ClientSession.java
src/java/org/opensrf/Request.java
src/java/org/opensrf/Session.java
src/java/org/opensrf/SessionException.java [new file with mode: 0644]
src/java/org/opensrf/Stack.java
src/java/org/opensrf/Status.java [new file with mode: 0644]
src/java/org/opensrf/Sys.java [new file with mode: 0644]
src/java/org/opensrf/net/xmpp/XMPPSession.java
src/java/org/opensrf/test/MathBench.java [new file with mode: 0644]
src/java/org/opensrf/test/TestCache.java [new file with mode: 0644]
src/java/org/opensrf/test/TestClient.java
src/java/org/opensrf/test/TestConfig.java
src/java/org/opensrf/test/TestSettings.java [new file with mode: 0644]
src/java/org/opensrf/util/Cache.java [new file with mode: 0644]
src/java/org/opensrf/util/Config.java
src/java/org/opensrf/util/ConfigException.java
src/java/org/opensrf/util/SettingsClient.java [new file with mode: 0644]
src/jserver/osrf_chat.c
src/jserver/osrf_chat_main.c
src/libstack/opensrf.c
src/libstack/osrfConfig.c
src/libstack/osrf_app_session.c
src/libstack/osrf_prefork.c
src/libstack/osrf_settings.c
src/libstack/osrf_system.c
src/libstack/osrf_system.h
src/libtransport/basic_client.c
src/libtransport/transport_client.c
src/libtransport/transport_client.h
src/libtransport/transport_session.c
src/libtransport/transport_session.h
src/objson/json2xml.h
src/objson/json_parser.h
src/objson/object.h
src/perlmods/OpenSRF/Utils/Config.pm
src/ports/strn_compat/Makefile [new file with mode: 0644]
src/ports/strn_compat/strndup.c [new file with mode: 0644]
src/ports/strn_compat/strndup.h [new file with mode: 0644]
src/ports/strn_compat/strnlen.c [new file with mode: 0644]
src/ports/strn_compat/strnlen.h [new file with mode: 0644]
src/python/osrf/gateway.py [new file with mode: 0644]
src/python/osrf/json.py
src/python/osrf/net_obj.py [new file with mode: 0644]
src/python/osrf/ses.py
src/python/osrf/utils.py
src/utils/log.c
src/utils/socket_bundle.c
src/utils/socket_bundle.h
src/utils/utils.c
src/utils/utils.h
src/utils/xml_utils.c

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..a23c57c
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,14 @@
+all:
+       @source install.conf && make -s -C src all
+
+jserver:
+       @source install.conf && make -s -C src jserver
+
+install:
+       @source install.conf && make -s -C src install
+
+jserver-install:
+       @source install.conf && make -s -C src jserver-install
+
+clean:
+       @make -s -C src clean
diff --git a/examples/srfsh_config.xsd b/examples/srfsh_config.xsd
new file mode 100644 (file)
index 0000000..9f1fd8d
--- /dev/null
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<!--
+
+Copyright (C) 2007 Laurentian University
+Dan Scott <dscott@laurentian.ca>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+
+-->
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+<!-- define types -->
+<xs:simpleType name="loglevelType">
+ <xs:restriction base="xs:positiveInteger">
+  <xs:maxInclusive value="4"/>
+ </xs:restriction>
+</xs:simpleType>
+
+<xs:simpleType name="portType">
+ <xs:restriction base="xs:positiveInteger">
+  <xs:maxInclusive value="65535"/>
+ </xs:restriction>
+</xs:simpleType>
+
+
+<!-- define simple elements -->
+<xs:element name="router_name" type="xs:string"/>
+<xs:element name="domain" type="xs:string"/>
+<xs:element name="username" type="xs:string"/>
+<xs:element name="passwd" type="xs:string"/>
+<xs:element name="port" type="portType"/>
+<xs:element name="logfile" type="xs:string"/>
+<xs:element name="loglevel" type="loglevelType"/>
+
+<!-- group type -->
+<xs:group name="srfshElements">
+ <xs:all>
+  <xs:element ref="router_name"/>
+  <xs:element ref="domains"/>
+  <xs:element ref="username"/>
+  <xs:element ref="passwd"/>
+  <xs:element ref="port"/>
+  <xs:element ref="logfile"/>
+  <xs:element ref="loglevel"/>
+ </xs:all>
+</xs:group>
+
+<!-- complex elements -->
+<xs:element name="domains">
+ <xs:complexType>
+  <xs:sequence>
+   <xs:element ref="domain" minOccurs="1" maxOccurs="unbounded"/>
+  </xs:sequence>
+ </xs:complexType>
+</xs:element>
+
+<xs:element name="srfsh">
+ <xs:complexType>
+  <xs:group ref="srfshElements"/>
+ </xs:complexType>
+</xs:element>
+
+</xs:schema>
diff --git a/install.conf b/install.conf
new file mode 100644 (file)
index 0000000..35911d6
--- /dev/null
@@ -0,0 +1,14 @@
+export PREFIX=/openils/
+export BINDIR=/openils//bin/
+export LIBDIR=/openils//lib/
+export PERLDIR=/openils//lib//perl5/
+export INCLUDEDIR=/openils//include/
+export ETCDIR=/openils//conf
+export SOCK=/openils//var/sock
+export PID=/openils//var/pid
+export LOG=/openils//var/log
+export TMP=/tmp/ilstemp
+export APXS2=/usr/bin/apxs2
+export APACHE2_HEADERS=/usr/include/apache2
+export APR_HEADERS=/usr/include/apr-1.0/
+export LIBXML2_HEADERS=/usr/include/libxml2/
index 0ad9171..8b33c95 100644 (file)
@@ -9,7 +9,7 @@ export PERLDIR                  = $(LIBDIR)/perl5
 export INCLUDEDIR              = $(PREFIX)/include
 
 export LDLIBS                  += 
-export LDFLAGS                 += -L $(TMPDIR) -L . -L /opt/lib
+export LDFLAGS                 += -Wl,-rpath=$(LIBDIR) -L $(TMPDIR) -L . -L /opt/lib
 export CFLAGS                  += -pipe -g -Wall -O2 -fPIC -I$(LIBXML2_HEADERS) -I$(APACHE2_HEADERS) \
                                                                -I$(LIBXML2_HEADERS)/libxml  -I$(TMP) \
                                                                -I$(APR_HEADERS) -I$(TMPDIR)
@@ -135,7 +135,6 @@ install-prep:
        mkdir -p $(INCLUDEDIR)
        mkdir -p $(INCLUDEDIR)/$(OPENSRF)
        mkdir -p $(ETCDIR)
-       mkdir -p $(TEMPLATEDIR)
 
 libopensrf-install:    install-prep
        @echo $@
index 67891e7..7bcd020 100644 (file)
@@ -2,7 +2,7 @@
 JAVA_LIBDIR = .lib
 JAVAC=javac -J-Xmx256m
 JAVA=java -Xmx256m 
-JAVA_LIBS = .:$(JAVA_LIBDIR):ext/json-jdk1.5-2007-05-01.jar:ext/wstx-asl-3.2.1.jar:ext/stax-api-1.0.1.jar
+JAVA_LIBS = .:$(JAVA_LIBDIR):ext/json-jdk1.5-2007-05-01.jar:ext/wstx-lgpl-3.2.1.jar:ext/stax-api-1.0.1.jar:ext/java_memcached-release_1.5.1.jar
 JAVA_SRC = \
        org/opensrf/net/xmpp/*.java \
        org/opensrf/util/*.java \
@@ -25,7 +25,15 @@ check:
        @echo -e "\nTruncating at 30 lines"
 
 run:
-       $(JAVA) -cp $(JAVA_LIBS) $(JAVA_EXE) $(JAVA_ARGS)
+       @$(JAVA) -cp $(JAVA_LIBS) $(JAVA_EXE) $(JAVA_ARGS)
+
+deps:
+       mkdir -p ext
+       wget 'http://woodstox.codehaus.org/stax-api-1.0.1.jar' -O ext/stax-api-1.0.1.jar
+       wget 'http://woodstox.codehaus.org/3.2.1/wstx-lgpl-3.2.1.jar' -O ext/wstx-lgpl-3.2.1.jar
+       wget 'http://img.whalin.com/memcached/jdk5/standard/java_memcached-release_1.5.1.jar' -O ext/java_memcached-release_1.5.1.jar
+       mkdir -p .tmp && cd .tmp && wget 'http://www.json.org/java/json.zip' && unzip json.zip
+       $(JAVAC) -d $(JAVA_LIBDIR) .tmp/org/json/*.java
 
 docs:
        find . -name *.java > files;
diff --git a/src/java/ext/stax-api-1.0.1.jar b/src/java/ext/stax-api-1.0.1.jar
deleted file mode 100644 (file)
index 162b3fb..0000000
Binary files a/src/java/ext/stax-api-1.0.1.jar and /dev/null differ
diff --git a/src/java/ext/wstx-asl-3.2.1.jar b/src/java/ext/wstx-asl-3.2.1.jar
deleted file mode 100644 (file)
index 581f825..0000000
Binary files a/src/java/ext/wstx-asl-3.2.1.jar and /dev/null differ
index 09cfce1..cc68505 100644 (file)
@@ -8,6 +8,7 @@ import java.util.Random;
 import java.util.Arrays;
 
 import org.opensrf.util.*;
+import org.opensrf.net.xmpp.*;
 
 
 /**
@@ -41,8 +42,8 @@ public class ClientSession extends Session {
         this.service = service;
 
         /** generate the remote node string */
-        domain = (String) Config.getFirst("/domains/domain");
-        router = Config.getString("/router_name");
+        domain = (String) Config.global().getFirst("/domains/domain");
+        router = Config.global().getString("/router_name");
         setRemoteNode(router + "@" + domain + "/" + service);
         origRemoteNode = getRemoteNode();
 
@@ -111,7 +112,7 @@ public class ClientSession extends Session {
      */
     public void pushResponse(Message msg) {
 
-        Request req = requests.get(new Integer(msg.getId()));
+        Request req = findRequest(msg.getId());
         if(req == null) {
             /** LOG that we've received a result to a non-existant request */
             return;
@@ -128,11 +129,21 @@ public class ClientSession extends Session {
         );
     }
 
+    public Request findRequest(int reqId) {
+        return requests.get(new Integer(reqId));
+    }
+
     /**
      * Removes a request for this session's request set
      */
     public void cleanupRequest(int reqId) {
         requests.remove(new Integer(reqId));
     }
+
+     public void setRequestComplete(int reqId) {
+        Request req = findRequest(reqId);
+        if(req == null) return;
+        req.setComplete();
+    }
 }
 
index 001ce43..e5d0ef6 100644 (file)
@@ -69,11 +69,11 @@ public class Request {
      * negative, this method will wait indefinitely.
      * @return The result or null if none arrives in time
      */
-    public Result recv(long millis) throws SessionException {
+    public Result recv(long millis) throws SessionException, MethodException {
 
         Result result = null;
 
-        if(millis < 0) {
+        if(millis < 0 && !complete) {
             /** wait potentially forever for a result to arrive */
             session.waitForMessage(millis);
             if((result = resultQueue.poll()) != null)
@@ -81,7 +81,7 @@ public class Request {
 
         } else {
 
-            while(millis >= 0) {
+            while(millis >= 0 && !complete) {
 
                 /** wait up to millis milliseconds for a result.  waitForMessage() 
                  * will return if a response to any request arrives, so we keep track
@@ -120,4 +120,9 @@ public class Request {
     public void cleanup() {
         session.cleanupRequest(id);
     }
+
+    /** Sets this request as complete */
+    public void setComplete() {
+        complete = true;
+    }
 }
index 3dc81f9..e2b41c3 100644 (file)
@@ -60,7 +60,7 @@ public abstract class Session {
      * all received messages to the stack for processing
      * @param millis The number of milliseconds to wait for a message to arrive
      */
-    public static void waitForMessage(long millis) throws SessionException {
+    public static void waitForMessage(long millis) throws SessionException, MethodException {
         try {
             Stack.processXMPPMessage(
                 XMPPSession.getGlobalSession().recv(millis));
diff --git a/src/java/org/opensrf/SessionException.java b/src/java/org/opensrf/SessionException.java
new file mode 100644 (file)
index 0000000..bd90a76
--- /dev/null
@@ -0,0 +1,13 @@
+package org.opensrf;
+/**
+ * Used by sessions to indicate communication errors
+ */
+public class SessionException extends Exception {
+    public SessionException(String info) {
+        super(info);
+    }
+    public SessionException(String info, Throwable cause) {
+        super(info, cause);
+    }
+}
+
index 6db285e..36dba52 100644 (file)
@@ -8,10 +8,12 @@ import java.util.Iterator;
 
 public class Stack {
 
-    public static void processXMPPMessage(XMPPMessage msg) {
+    public static void processXMPPMessage(XMPPMessage msg) throws MethodException {
 
         if(msg == null) return;
 
+        //System.out.println(msg.getBody());
+
         /** fetch this session from the cache */
         Session ses = Session.findCachedSession(msg.getThread());
 
@@ -55,7 +57,7 @@ public class Stack {
         /** LOG the duration */
     }
 
-    private static void processOSRFMessage(Session ses, Message msg) {
+    private static void processOSRFMessage(Session ses, Message msg) throws MethodException {
         if( ses instanceof ClientSession ) 
             processResponse((ClientSession) ses, msg);
         else
@@ -65,11 +67,30 @@ public class Stack {
     /** 
      * Process a server response
      */
-    private static void processResponse(ClientSession session, Message msg) {
-        if(msg.RESULT.equals(msg.getType())) {
+    private static void processResponse(ClientSession session, Message msg) throws MethodException {
+        String type = msg.getType();
+
+        if(msg.RESULT.equals(type)) {
             session.pushResponse(msg);
             return;
         }
+
+        if(msg.STATUS.equals(type)) {
+
+            OSRFObject obj = (OSRFObject) msg.getPayload();
+            Status stat = new Status(obj.getString("status"), obj.getInt("statusCode"));
+            int statusCode = stat.getStatusCode();
+            String status = stat.getStatus();
+
+            switch(statusCode) {
+                case Status.COMPLETE:
+                    session.setRequestComplete(msg.getId());
+                    break;
+                case Status.NOTFOUND: 
+                    session.setRequestComplete(msg.getId());
+                    throw new MethodException(status);
+            }
+        }
     }
 
     /**
diff --git a/src/java/org/opensrf/Status.java b/src/java/org/opensrf/Status.java
new file mode 100644 (file)
index 0000000..8026c7b
--- /dev/null
@@ -0,0 +1,63 @@
+package org.opensrf;
+import org.opensrf.util.*;
+
+public class Status {
+
+    public static final int CONTINUE            = 100;
+    public static final int OK                  = 200;
+    public static final int ACCEPTED            = 202;
+    public static final int COMPLETE            = 205;
+    public static final int REDIRECTED          = 307;
+    public static final int EST                 = 400;
+    public static final int STATUS_UNAUTHORIZED = 401;
+    public static final int FORBIDDEN           = 403;
+    public static final int NOTFOUND            = 404;
+    public static final int NOTALLOWED          = 405;
+    public static final int TIMEOUT             = 408;
+    public static final int EXPFAILED           = 417;
+    public static final int INTERNALSERVERERROR = 500;
+    public static final int NOTIMPLEMENTED      = 501;
+    public static final int VERSIONNOTSUPPORTED = 505;
+
+    private OSRFRegistry registry = OSRFRegistry.registerObject(
+        "osrfConnectStatus",
+        OSRFRegistry.WireProtocol.HASH,
+        new String[] {"status", "statusCode"});
+
+    /** The name of the status */
+    String status;
+    /** The status code */
+    int statusCode;
+
+    public Status(String status, int statusCode) {
+        this.status = status;
+        this.statusCode = statusCode;
+    }
+
+    public int getStatusCode() {
+        return statusCode;
+    }
+    public String getStatus() {
+        return status;
+    }
+
+    /**
+     * Implements the generic get() API required by OSRFSerializable
+     */
+    public Object get(String field) {
+        if("status".equals(field))
+            return getStatus();
+        if("statusCode".equals(field))
+            return new Integer(getStatusCode());
+        return null;
+    }
+
+    /**
+     * @return The osrfMessage registry.
+     */
+    public OSRFRegistry getRegistry() {
+        return registry;
+    }
+}
+
+
diff --git a/src/java/org/opensrf/Sys.java b/src/java/org/opensrf/Sys.java
new file mode 100644 (file)
index 0000000..8520838
--- /dev/null
@@ -0,0 +1,47 @@
+package org.opensrf;
+
+import org.opensrf.util.*;
+import org.opensrf.net.xmpp.*;
+
+
+public class Sys {
+
+    /**
+     * Connects to the OpenSRF network so that client sessions may communicate.
+     * @param configFile The OpenSRF config file 
+     * @param configContext Where in the XML document the config chunk lives.  This
+     * allows an OpenSRF client config chunk to live in XML files where other config
+     * information lives.
+     */
+    public static void bootstrapClient(String configFile, String configContext) 
+            throws ConfigException, SessionException  {
+
+        /** create the config parser */
+        Config config = new Config(configContext);
+        config.parse(configFile);
+        Config.setConfig(config); /* set this as the global config */
+
+        /** Collect the network connection info from the config */
+        String username = config.getString("/username");
+        String passwd = config.getString("/passwd");
+        String host = (String) config.getFirst("/domains/domain");
+        int port = config.getInt("/port");
+
+        try {
+            /** Connect to the Jabber network */
+            XMPPSession xses = new XMPPSession(host, port);
+            xses.connect(username, passwd, "test-java"); /* XXX */
+            XMPPSession.setGlobalSession(xses);
+        } catch(XMPPException e) {
+            throw new SessionException("Unable to bootstrap client", e);
+        }
+    }
+
+    /**
+     * Shuts down the connection to the opensrf network
+     */
+    public static void shutdown() {
+        XMPPSession.getGlobalSession().disconnect();
+    }
+}
+
index ce7e36c..e8b639e 100644 (file)
@@ -19,6 +19,8 @@ public class XMPPSession {
         "<iq id='123' type='set'><query xmlns='jabber:iq:auth'>" +
         "<username>%s</username><password>%s</password><resource>%s</resource></query></iq>";
 
+    public static final String JABBER_DISCONNECT = "</stream:stream>";
+
     /** jabber domain */
     private String host;
     /** jabber port */
@@ -36,6 +38,8 @@ public class XMPPSession {
     PrintWriter writer;
     /** Raw socket output stream */
     OutputStream outStream;
+    /** The raw socket */
+    Socket socket;
 
     /** The process-wide session.  All communication occurs
      * accross this single connection */
@@ -88,8 +92,6 @@ public class XMPPSession {
         this.password = password;
         this.resource = resource;
 
-        Socket socket;
-
         try { 
             /* open the socket and associated streams */
             socket = new Socket(host, port);
@@ -193,5 +195,16 @@ public class XMPPSession {
 
         return null;
     }
+
+
+    /**
+     * Disconnects from the jabber server and closes the socket
+     */
+    public void disconnect() {
+        try {
+            outStream.write(JABBER_DISCONNECT.getBytes());
+            socket.close();
+        } catch(Exception e) {}
+    }
 }
 
diff --git a/src/java/org/opensrf/test/MathBench.java b/src/java/org/opensrf/test/MathBench.java
new file mode 100644 (file)
index 0000000..b6e67f9
--- /dev/null
@@ -0,0 +1,79 @@
+package org.opensrf.test;
+import org.opensrf.*;
+import org.opensrf.util.*;
+import java.util.Date;
+import java.util.List;
+import java.util.ArrayList;
+import java.io.PrintStream;
+
+
+public class MathBench {
+
+    public static void main(String args[]) throws Exception {
+
+        PrintStream out = System.out;
+
+        if(args.length < 2) {
+            out.println("usage: java org.opensrf.test.MathBench <osrfConfig> <numIterations>");
+            return;
+        }
+
+        /** connect to the opensrf network */
+        Sys.bootstrapClient(args[0], "/config/opensrf");
+
+        /** how many iterations */
+        int count = Integer.parseInt(args[1]);
+
+        /** create the client session */
+        ClientSession session = new ClientSession("opensrf.math");
+
+        /** params are 1,2 */
+        List<Object> params = new ArrayList<Object>();
+        params.add(new Integer(1));
+        params.add(new Integer(2));
+
+        Request request;
+        Result result;
+        long start;
+        double total = 0;
+
+        for(int i = 0; i < count; i++) {
+
+            start = new Date().getTime();
+
+            /** create (and send) the request */
+            request = session.request("add", params);
+
+            /** wait up to 3 seconds for a response */
+            result = request.recv(3000);
+
+            /** collect the round-trip time */
+            total += new Date().getTime() - start;
+
+            if(result.getStatusCode() == Status.OK) {
+                out.print("+");
+            } else {
+                out.println("\nrequest failed");
+                out.println("status = " + result.getStatus());
+                out.println("status code = " + result.getStatusCode());
+            }
+
+            /** remove this request from the session's request set */
+            request.cleanup();
+
+            if((i+1) % 100 == 0) /** print 100 responses per line */
+                out.println(" [" + (i+1) + "]");
+        }
+
+        out.println("\nAverage request time is " + (total/count) + " ms");
+        
+        /** remove this session from the global session cache */
+        session.cleanup();
+
+        /** disconnect from the opensrf network */
+        Sys.shutdown();
+    }
+}
+
+
+
diff --git a/src/java/org/opensrf/test/TestCache.java b/src/java/org/opensrf/test/TestCache.java
new file mode 100644 (file)
index 0000000..1e47c32
--- /dev/null
@@ -0,0 +1,27 @@
+package org.opensrf.test;
+import org.opensrf.*;
+import org.opensrf.util.*;
+import java.util.List;
+import java.util.ArrayList;
+
+public class TestCache {
+    public static void main(String args[]) throws Exception {
+
+        /**
+         * args is a list of string like so:  server:port server2:port server3:port ...
+         */
+
+        Cache.initCache(args);
+        Cache cache = new Cache();
+
+        cache.set("key1", "HI, MA!");
+        cache.set("key2", "HI, MA! 2");
+        cache.set("key3", "HI, MA! 3");
+
+        System.out.println("got key1 = " + (String) cache.get("key1"));
+        System.out.println("got key2 = " + (String) cache.get("key2"));
+        System.out.println("got key3 = " + (String) cache.get("key3"));
+    }
+}
+
+
index 8cd7865..2625053 100644 (file)
@@ -1,61 +1,54 @@
 package org.opensrf.test;
 import org.opensrf.*;
 import org.opensrf.util.*;
-import org.opensrf.net.xmpp.*;
-import java.io.PrintStream;
 import java.util.Map;
 import java.util.Date;
+import java.util.List;
+import java.util.ArrayList;
+import java.io.PrintStream;
 
 
 public class TestClient {
+
     public static void main(String args[]) throws Exception {
-        
+
         PrintStream out = System.out;
+        if(args.length < 3) {
+            out.println( "usage: org.opensrf.test.TestClient "+
+                "<osrfConfigFile> <service> <method> [<JSONparam1>, <JSONparam2>]");
+            return;
+        }
 
-        try {
-
-            /** setup the config parser */
-            String configFile = args[0];
-            Config config = new Config("/config/opensrf");
-            config.parse(configFile);
-            Config.setConfig(config);
-
-            /** Connect to jabber */
-            String username = Config.getString("/username");
-            String passwd = Config.getString("/passwd");
-            String host = (String) Config.getFirst("/domains/domain");
-            int port = Config.getInt("/port");
-            XMPPSession xses = new XMPPSession(host, port);
-            xses.connect(username, passwd, "test-java-client");
-            XMPPSession.setGlobalSession(xses);
-    
-            /** build the client session and send the request */
-            ClientSession session = new ClientSession("opensrf.settings");
-            Request request = session.request(
-                "opensrf.settings.host_config.get", 
-                new String[] {args[1]}
-            );
-
-            Result result = request.recv(10000);
-            if(result == null) {
-                out.println("no result");
-                return;
-            }
+        Sys.bootstrapClient(args[0], "/config/opensrf");
+        String service = args[1];
+        String method = args[2];
 
-            out.println("status = " + result.getStatus());
-            out.println("status code = " + result.getStatusCode());
+        /** build the client session and send the request */
+        ClientSession session = new ClientSession(service);
+        List<Object> params = new ArrayList<Object>();
+        JSONReader reader;
 
-            out.println("setting config memcache server(s) = " +
-                new JSONWriter(
-                    Utils.findPath( (Map) result.getContent(), 
-                    "/cache/global/servers/server")
-                ).write());
+        for(int i = 3; i < args.length; i++) /* add the params */
+            params.add(new JSONReader(args[i]).read());
 
 
-        } catch(ArrayIndexOutOfBoundsException e) {
-            out.println("usage: org.opensrf.test.TestClient <osrfConfigFile> <domain>");
-            return;
+        Result result;
+
+        long start = new Date().getTime();
+        Request request = session.request(method, params);
+
+        while( (result = request.recv(60000)) != null ) { 
+            /** loop over the results and print the JSON version of the content */
+
+            if(result.getStatusCode() != 200) { /* make sure the request succeeded */
+                out.println("status = " + result.getStatus());
+                out.println("status code = " + result.getStatusCode());
+                continue;
+            }
+
+            out.println("result JSON: " + new JSONWriter(result.getContent()).write());
         }
+        out.println("Request round trip took: " + (new Date().getTime() - start) + " ms.");
     }
 }
 
index 5cd4eb3..f65a84f 100644 (file)
@@ -11,6 +11,6 @@ public class TestConfig {
         System.out.println("");
 
         for(int i = 1; i < args.length; i++) 
-            System.out.println("Found config value: " + args[i] + ": " + Config.get(args[i]));
+            System.out.println("Found config value: " + args[i] + ": " + Config.global().get(args[i]));
     }
 }
diff --git a/src/java/org/opensrf/test/TestSettings.java b/src/java/org/opensrf/test/TestSettings.java
new file mode 100644 (file)
index 0000000..116bbe1
--- /dev/null
@@ -0,0 +1,14 @@
+package org.opensrf.test;
+import org.opensrf.*;
+import org.opensrf.util.*;
+
+public class TestSettings {
+    public static void main(String args[]) throws Exception {
+        Sys.bootstrapClient(args[0], "/config/opensrf");
+        SettingsClient client = SettingsClient.instance();
+        String lang = client.getString("/apps/opensrf.settings/language");
+        String impl = client.getString("/apps/opensrf.settings/implementation");
+        System.out.println("opensrf.settings language = " + lang);
+        System.out.println("opensrf.settings implementation = " + impl);
+    }
+}
diff --git a/src/java/org/opensrf/util/Cache.java b/src/java/org/opensrf/util/Cache.java
new file mode 100644 (file)
index 0000000..5303688
--- /dev/null
@@ -0,0 +1,38 @@
+package org.opensrf.util;
+import com.danga.MemCached.*;
+import java.util.List;
+
+/**
+ * Memcache client
+ */
+public class Cache extends MemCachedClient {
+
+    public Cache() {
+        super();
+        setCompressThreshold(4096); /* ?? */
+    }
+
+    /**
+     * Initializes the cache client
+     * @param serverList Array of server:port strings specifying the
+     * set of memcache servers this client will talk to
+     */
+    public static void initCache(String[] serverList) {
+        SockIOPool pool = SockIOPool.getInstance();
+        pool.setServers(serverList);
+        pool.initialize();      
+        com.danga.MemCached.Logger logger = 
+            com.danga.MemCached.Logger.getLogger(MemCachedClient.class.getName());
+        logger.setLevel(logger.LEVEL_ERROR);
+    }
+
+    /**
+     * Initializes the cache client
+     * @param serverList List of server:port strings specifying the
+     * set of memcache servers this client will talk to
+     */
+    public static void initCache(List<String> serverList) {
+        initCache(serverList.toArray(new String[]{}));
+    }
+}
+
index 7b3a0bf..ddac9c0 100644 (file)
@@ -23,6 +23,11 @@ public class Config {
      */
     private String context;
 
+    public static Config global() {
+        return config;
+    }
+
+
     /**
      * @param context The config context
      */
@@ -34,7 +39,7 @@ public class Config {
      * Sets the global config object.
      * @param c The config object to use.
      */
-    public static void setConfig(Config c) {
+    public static void setGlobalConfig(Config c) {
         config = c;
     }
 
@@ -42,19 +47,36 @@ public class Config {
      * Parses an XML config file.
      * @param filename The path to the file to parse.
      */
-    public void parse(String filename) throws Exception {
-        String xml = Utils.fileToString(filename);
-        JSONObject jobj = XML.toJSONObject(xml);
-        configObject = (Map) new JSONReader(jobj.toString()).readObject();
+    public void parse(String filename) throws ConfigException {
+        try {
+            String xml = Utils.fileToString(filename);
+            JSONObject jobj = XML.toJSONObject(xml);
+            configObject = (Map) new JSONReader(jobj.toString()).readObject();
+        } catch(Exception e) {
+            throw new ConfigException("Error parsing config", e);
+        }
     }
 
+    public static void setConfig(Config conf) {
+        config = conf;
+    }
+
+    public void setConfigObject(Map config) {
+        this.configObject = config;
+    }
+
+    protected Map getConfigObject() {
+        return this.configObject;
+    }
+
+
     /**
      * Returns the configuration value found at the requested path.
      * @param path The search path
      * @return The config value, or null if no value exists at the given path.  
      * @throws ConfigException thrown if nothing is found at the path
      */
-    public static String getString(String path) throws ConfigException {
+    public String getString(String path) throws ConfigException {
         try {
             return (String) get(path);
         } catch(Exception e) {
@@ -67,7 +89,7 @@ public class Config {
      * Gets the int value at the given path
      * @param path The search path
      */
-    public static int getInt(String path) throws ConfigException {
+    public int getInt(String path) throws ConfigException {
         try {
             return Integer.parseInt(getString(path));
         } catch(Exception e) {
@@ -82,9 +104,9 @@ public class Config {
      * @return The config value
      * @throws ConfigException thrown if nothing is found at the path
      */
-    public static Object get(String path) throws ConfigException {
+    public Object get(String path) throws ConfigException {
         try {
-            Object obj = Utils.findPath(config.configObject, config.context + path);
+            Object obj = Utils.findPath(configObject, context + path);
             if(obj == null)
                 throw new ConfigException("");
             return obj;
@@ -99,7 +121,7 @@ public class Config {
      * no list is found, ConfigException is thrown.
      * @param path The search path
      */
-    public static Object getFirst(String path) throws ConfigException {
+    public Object getFirst(String path) throws ConfigException {
         Object obj = get(path); 
         if(obj instanceof List) 
             return ((List) obj).get(0);
index be7c0cf..c1c491e 100644 (file)
@@ -8,4 +8,7 @@ public class ConfigException extends Exception {
     public ConfigException(String info) {
         super(info);
     }
+    public ConfigException(String info, Throwable t) {
+        super(info, t);
+    }
 }
diff --git a/src/java/org/opensrf/util/SettingsClient.java b/src/java/org/opensrf/util/SettingsClient.java
new file mode 100644 (file)
index 0000000..cd70ebb
--- /dev/null
@@ -0,0 +1,53 @@
+package org.opensrf.util;
+import org.opensrf.*;
+import java.util.Map;
+
+/**
+ * Connects to the OpenSRF Settings server to fetch the settings config.  
+ * Provides a Config interface for fetching settings via path
+ */
+public class SettingsClient extends Config {
+
+    /** Singleton SettingsClient instance */
+    private static SettingsClient client = new SettingsClient();
+
+    public SettingsClient() {
+        super("");
+    }
+
+    /**
+     * @return The global settings client instance 
+     */
+    public static SettingsClient instance() throws ConfigException {
+        if(client.getConfigObject() == null) 
+            client.fetchConfig();
+        return client;
+    }
+
+    /**
+     * Fetches the settings object from the settings server
+     */
+    private void fetchConfig() throws ConfigException {
+
+        ClientSession ses = new ClientSession("opensrf.settings");
+        try {
+
+            Request req = ses.request(
+                "opensrf.settings.host_config.get", 
+                new String[]{(String)Config.global().getFirst("/domains/domain")});
+    
+            Result res = req.recv(12000);
+            if(res == null) {
+                /** throw exception */
+            }
+            setConfigObject((Map) res.getContent());
+
+        } catch(Exception e) {
+            throw new ConfigException("Error fetching settings config", e);
+
+        } finally {
+            ses.cleanup();
+        }
+    }
+}
+
index 55b3c33..2585719 100644 (file)
@@ -18,8 +18,8 @@ GNU General Public License for more details.
 #include <stdio.h>
 #include <time.h>
 
-int __osrfChatXMLErrorOcurred = 0;
-int __osrfChatClientSentDisconnect = 0;
+static int osrfChatXMLErrorOcurred = 0;
+static int osrfChatClientSentDisconnect = 0;
 
 /* shorter version of strcmp */
 static int eq(const char* a, const char* b) { return (a && b && !strcmp(a,b)); }
@@ -83,14 +83,16 @@ osrfChatServer* osrfNewChatServer( char* domain, char* secret, int s2sport ) {
        server->deadNodes = osrfNewList();
        server->nodeList->freeItem = &osrfChatNodeFree;
        server->domain          = strdup(domain);
+       server->secret      = strdup(secret);
        server->s2sport = s2sport;
+       server->port        = 0;
 
+       // Build socket manager
        server->mgr = safe_malloc(sizeof(socket_manager));
        server->mgr->data_received = &osrfChatHandleData;
        server->mgr->blob = server;
        server->mgr->on_socket_closed = &osrfChatSocketClosed;
 
-       if(secret) server->secret = strdup(secret);
        return server;
 }
 
@@ -192,8 +194,12 @@ void osrfChatServerFree(osrfChatServer* server ) {
        if(!server) return;
        osrfHashFree(server->nodeHash);
        osrfListFree(server->nodeList);
+       osrfListFree(server->deadNodes);
        free(server->mgr);
+       free(server->domain);
        free(server->secret);
+
+       free(server);
 }
 
 
@@ -399,16 +405,16 @@ int osrfChatPushData( osrfChatServer* server, osrfChatNode* node, char* data ) {
        xmlParseChunk(node->parserCtx, data, strlen(data), 0);
        node->inparse = 0;
 
-       if(__osrfChatXMLErrorOcurred) {
-               __osrfChatXMLErrorOcurred = 0;
+       if(osrfChatXMLErrorOcurred) {
+               osrfChatXMLErrorOcurred = 0;
                return -1;
        }
 
        /* we can't do cleanup of the XML handlers while in the middle of a 
                data push, so set flags in the data push and doe the cleanup here */
        /*
-       if(__osrfChatClientSentDisconnect) {
-               __osrfChatClientSentDisconnect  = 0;
+       if(osrfChatClientSentDisconnect) {
+               osrfChatClientSentDisconnect  = 0;
                osrfChatNodeFinish( server, node );
        }
        */
@@ -587,7 +593,7 @@ int osrfChatHandleNewConnection( osrfChatNode* node, const char* name, const xml
 char* osrfChatMkAuthKey() {
        char keybuf[112];
        bzero(keybuf, 112);
-       snprintf(keybuf, 111, "%d%d%s", (int) time(NULL), getpid(), getenv("HOSTNAME"));
+       snprintf(keybuf, 111, "%d%ld%s", (int) time(NULL), (long) getpid(), getenv("HOSTNAME"));
        return strdup(shahash(keybuf));
 }
 
@@ -797,7 +803,7 @@ void osrfChatHandleCharacter( void* blob, const xmlChar *ch, int len) {
 
 void osrfChatParseError( void* blob, const char* msg, ... ) {
 
-       __osrfChatXMLErrorOcurred = 1;
+       osrfChatXMLErrorOcurred = 1;
 }
 
 
index 401d3b4..8ac5298 100644 (file)
@@ -13,6 +13,10 @@ int main( int argc, char* argv[] ) {
        }
 
        osrfConfig* cfg = osrfConfigInit( argv[1], argv[2] );
+       if( !cfg ) {
+               fprintf( stderr, "Unable to load configuration file %s\n", argv[1] );
+               return -1;
+       }
 
        init_proc_title( argc, argv );
        set_proc_title( "ChopChop" );
@@ -26,6 +30,27 @@ int main( int argc, char* argv[] ) {
        char* lfile                     = osrfConfigGetValue(cfg, "/logfile");
        char* facility          = osrfConfigGetValue(cfg, "/syslog");
 
+       if(!domain)
+               fputs( "No domain specified in configuration file\n", stderr );
+       
+       if(!secret)
+               fputs( "No secret specified in configuration file\n", stderr );
+       
+       if(!sport)
+               fputs( "No port specified in configuration file\n", stderr );
+       
+       if(!listenaddr)
+               fputs( "No listen_address specified in configuration file\n", stderr );
+       
+       if(!llevel)
+               fputs( "No loglevel specified in configuration file\n", stderr );
+       
+       if(!lfile)
+               fputs( "No logfile specified in configuration file\n", stderr );
+       
+       if(!s2sport)
+               fputs( "No s2sport specified in configuration file\n", stderr );
+       
        if(!(domain && secret && sport && listenaddr && llevel && lfile && s2sport)) {
                fprintf(stderr, "Configuration error for ChopChop - missing key ingredient\n");
                return -1;
@@ -35,10 +60,8 @@ int main( int argc, char* argv[] ) {
        int s2port = atoi(s2sport);
        int level = atoi(llevel);
 
-       if(!lfile) { fprintf(stderr, "Log file needed\n"); return -1; }
-
        if(!strcmp(lfile, "syslog")) {
-               osrfLogInit( OSRF_LOG_TYPE_SYSLOG, "chochop", level );
+               osrfLogInit( OSRF_LOG_TYPE_SYSLOG, "chopchop", level );
                osrfLogSetSyslogFacility(osrfLogFacilityToInt(facility));
 
        } else {
index 2277eb4..9291930 100644 (file)
@@ -21,13 +21,22 @@ int main( int argc, char* argv[] ) {
        init_proc_title( argc, argv );
        set_proc_title( "OpenSRF System-C" );
 
-       osrfSystemBootstrap( host, config, context );
+       int ret = osrfSystemBootstrap( host, config, context );
+
+       if (ret != 0) {
+               osrfLogError(
+                       OSRF_LOG_MARK,
+                       "Server Loop returned an error condition, exiting with %d",
+                       ret
+               );
+       }
+
 
        free(host);
        free(config);
        free(context);
 
-       return 0;
+       return ret;
 }
 
 
index c195a19..81e6623 100644 (file)
@@ -1,11 +1,15 @@
 /* defines the currently used bootstrap config file */
 #include "osrfConfig.h"
 
-osrfConfig* __osrfConfigDefault = NULL;
+static osrfConfig* osrfConfigDefault = NULL;
 
 
 void osrfConfigSetDefaultConfig(osrfConfig* cfg) {
-       if(cfg) __osrfConfigDefault = cfg;
+       if(cfg) {
+               if( osrfConfigDefault )
+                       osrfConfigFree( osrfConfigDefault );
+               osrfConfigDefault = cfg;
+       }
 }
 
 void osrfConfigFree(osrfConfig* cfg) {
@@ -18,13 +22,13 @@ void osrfConfigFree(osrfConfig* cfg) {
 
 
 int osrfConfigHasDefaultConfig() {
-       return ( __osrfConfigDefault != NULL );
+       return ( osrfConfigDefault != NULL );
 }
 
 
 void osrfConfigCleanup() { 
-       osrfConfigFree(__osrfConfigDefault); 
-       __osrfConfigDefault = NULL; 
+       osrfConfigFree(osrfConfigDefault);
+       osrfConfigDefault = NULL;
 }
 
 
@@ -37,19 +41,17 @@ void osrfConfigReplaceConfig(osrfConfig* cfg, const jsonObject* obj) {
 osrfConfig* osrfConfigInit(char* configFile, char* configContext) {
        if(!configFile) return NULL;
 
-       osrfConfigFree(__osrfConfigDefault);
-
-       osrfConfig* cfg = safe_malloc(sizeof(osrfConfig));
-       if(configContext) cfg->configContext = strdup(configContext);
-       else cfg->configContext = NULL;
-
+       // Load XML from the configuration file
+       
        xmlDocPtr doc = xmlParseFile(configFile);
        if(!doc) {
                osrfLogWarning( OSRF_LOG_MARK,  "Unable to parse XML config file %s", configFile);
                return NULL;
        }
 
-       cfg->config = xmlDocToJSON(doc);
+       // Translate it into a jsonObject
+       
+       jsonObject* json_config = xmlDocToJSON(doc);
 
        /*
        char* j = jsonObjectToJSON(cfg->config);
@@ -59,19 +61,28 @@ osrfConfig* osrfConfigInit(char* configFile, char* configContext) {
 
        xmlFreeDoc(doc);
 
-       if(!cfg->config) {
+       if(!json_config ) {
                osrfLogWarning( OSRF_LOG_MARK, "xmlDocToJSON failed for config %s", configFile);
                return NULL;
        }       
 
+       // Build an osrfConfig and return it by pointer
+       
+       osrfConfig* cfg = safe_malloc(sizeof(osrfConfig));
+
+       if(configContext) cfg->configContext = strdup(configContext);
+       else cfg->configContext = NULL;
+
+       cfg->config = json_config;
+       
        return cfg;
 }
 
 char* osrfConfigGetValue(osrfConfig* cfg, char* path, ...) {
 
        if(!path) return NULL;
-       if(!cfg) cfg = __osrfConfigDefault;
-       if(!cfg) { osrfLogWarning( OSRF_LOG_MARK, "No Confif object!"); return NULL; }
+       if(!cfg) cfg = osrfConfigDefault;
+       if(!cfg) { osrfLogWarning( OSRF_LOG_MARK, "No Config object in osrfConfigGetValue()"); return NULL; }
 
        VA_LIST_TO_STRING(path);
 
@@ -95,7 +106,7 @@ char* osrfConfigGetValue(osrfConfig* cfg, char* path, ...) {
 int osrfConfigGetValueList(osrfConfig* cfg, osrfStringArray* arr, char* path, ...) {
 
        if(!arr || !path) return 0;
-       if(!cfg) cfg = __osrfConfigDefault;
+       if(!cfg) cfg = osrfConfigDefault;
        if(!cfg) { osrfLogWarning( OSRF_LOG_MARK, "No Config object!"); return -1;}
 
        VA_LIST_TO_STRING(path);
index 770446f..095e50e 100644 (file)
@@ -229,7 +229,7 @@ osrf_app_session* osrf_app_client_session_init( char* remote_service ) {
        char id[256];
        memset(id,0,256);
 
-       sprintf(id, "%f.%d%d", get_timestamp_millis(), (int)time(NULL), getpid());
+       sprintf(id, "%f.%d%ld", get_timestamp_millis(), (int)time(NULL), (long) getpid());
        session->session_id = strdup(id);
        osrfLogDebug( OSRF_LOG_MARK,  "Building a new client session with id [%s] [%s]", 
                        session->remote_service, session->session_id );
@@ -598,6 +598,7 @@ int osrfAppRequestRespond( osrfAppSession* ses, int requestId, jsonObject* data
        if(!ses || ! data ) return -1;
 
        osrf_message* msg = osrf_message_init( RESULT, requestId, 1 );
+       osrf_message_set_status_info( msg, NULL, "OK", OSRF_STATUS_OK );
        char* json = jsonObjectToJSON( data );
 
        osrf_message_set_result_content( msg, json );
index 31548e9..1ea5959 100644 (file)
@@ -586,7 +586,7 @@ void prefork_child_wait( prefork_child* child ) {
                if( errno == EAGAIN ) n = 0;
 
       if( errno == EPIPE ) {
-         osrfLogWarning(OSRF_LOG_MARK, "C child attempted read on broken pipe, exiting...");
+         osrfLogDebug(OSRF_LOG_MARK, "C child attempted read on broken pipe, exiting...");
          break;
       }
 
@@ -606,8 +606,8 @@ void prefork_child_wait( prefork_child* child ) {
 
        buffer_free(gbuf);
 
-       osrfLogDebug( OSRF_LOG_MARK, "Child with max-requests=%d, num-served=%d exiting...[%d]", 
-                       child->max_requests, i, getpid() );
+       osrfLogDebug( OSRF_LOG_MARK, "Child with max-requests=%d, num-served=%d exiting...[%ld]", 
+                       child->max_requests, i, (long) getpid() );
 
    osrf_prefork_child_exit(child); /* just to be sure */
 }
index fa8d98e..26e3b8f 100644 (file)
@@ -4,6 +4,14 @@ osrf_host_config* config = NULL;
 
 char* osrf_settings_host_value(char* format, ...) {
        VA_LIST_TO_STRING(format);
+
+       if( ! config ) {
+               const char * msg = "NULL config pointer";
+               fprintf( stderr, "osrf_settings_host_value: %s\n", msg );
+               osrfLogError( OSRF_LOG_MARK, msg );
+               exit( 99 );
+       }
+
        jsonObject* o = jsonObjectFindPath(config->config, VA_BUF);
        char* val = jsonObjectToSimpleString(o);
        jsonObjectFree(o);
@@ -36,7 +44,17 @@ int osrf_settings_retrieve(char* hostname) {
                osrf_message* omsg = osrf_app_session_request_recv( session, req_id, 60 );
                jsonObjectFree(params);
 
-               if(omsg && omsg->_result_content) {
+               if(!omsg) {
+                       osrfLogError( OSRF_LOG_MARK, "No osrf_message received from host %s (timeout?)", hostname);
+               } else if(!omsg->_result_content) {
+                       osrf_message_free(omsg);
+                       osrfLogError(
+                               OSRF_LOG_MARK,
+                               "NULL or non-existant osrf_message result content received from host %s, "
+                               "broken message or no settings for host",
+                               hostname
+                       );
+               } else {
                        config = osrf_settings_new_host_config(hostname);
                        config->config = jsonObjectClone(omsg->_result_content);
                        osrf_message_free(omsg);
index 68f2e3c..dc6b2ba 100644 (file)
@@ -3,20 +3,20 @@
 #include "osrf_application.h"
 #include "osrf_prefork.h"
 
-void __osrfSystemSignalHandler( int sig );
+static int _osrfSystemInitCache( void );
 
-transport_client* __osrfGlobalTransportClient = NULL;
+static transport_client* osrfGlobalTransportClient = NULL;
 
-transport_client* osrfSystemGetTransportClient() {
-       return __osrfGlobalTransportClient;
+transport_client* osrfSystemGetTransportClient( void ) {
+       return osrfGlobalTransportClient;
 }
 
 void osrfSystemIgnoreTransportClient() {
-       __osrfGlobalTransportClient = NULL;
+       osrfGlobalTransportClient = NULL;
 }
 
-transport_client* osrf_system_get_transport_client() {
-       return __osrfGlobalTransportClient;
+transport_client* osrf_system_get_transport_client( void ) {
+       return osrfGlobalTransportClient;
 }
 
 int osrf_system_bootstrap_client( char* config_file, char* contextnode ) {
@@ -28,7 +28,7 @@ int osrfSystemBootstrapClientResc( char* config_file, char* contextnode, char* r
 }
 
 
-int _osrfSystemInitCache() {
+static int _osrfSystemInitCache( void ) {
 
        jsonObject* cacheServers = osrf_settings_host_value_object("/cache/global/servers/server");
        char* maxCache = osrf_settings_host_value("/cache/global/max_cache_time");
@@ -64,13 +64,22 @@ int osrfSystemBootstrap( char* hostname, char* configfile, char* contextNode ) {
 
        /* first we grab the settings */
        if(!osrfSystemBootstrapClientResc(configfile, contextNode, "settings_grabber" )) {
-               osrfLogError( OSRF_LOG_MARK, "Unable to bootstrap");
+               osrfLogError( OSRF_LOG_MARK,
+                       "Unable to bootstrap for host %s from configuration file %s",
+                       hostname, configfile );
                return -1;
        }
 
-       osrf_settings_retrieve(hostname);
+       int retcode = osrf_settings_retrieve(hostname);
        osrf_system_disconnect_client();
 
+       if( retcode ) {
+               osrfLogError( OSRF_LOG_MARK,
+                       "Unable to retrieve settings for host %s from configuration file %s",
+                       hostname, configfile );
+               return -1;
+       }
+       
        jsonObject* apps = osrf_settings_host_value_object("/activeapps/appname");
        osrfStringArray* arr = osrfNewStringArray(8);
        
@@ -105,11 +114,11 @@ int osrfSystemBootstrap( char* hostname, char* configfile, char* contextNode ) {
 
                                osrfLogInfo( OSRF_LOG_MARK, "Launching application %s with implementation %s", appname, libfile);
                
-                               int pid;
+                               pid_t pid;
                
                                if( (pid = fork()) ) { 
                                        // storage pid in local table for re-launching dead children...
-                                       osrfLogInfo( OSRF_LOG_MARK, "Launched application child %d", pid);
+                                       osrfLogInfo( OSRF_LOG_MARK, "Launched application child %ld", (long) pid);
        
                                } else {
                
@@ -117,7 +126,7 @@ int osrfSystemBootstrap( char* hostname, char* configfile, char* contextNode ) {
                                        if( osrfAppRegisterApplication( appname, libfile ) == 0 ) 
                                                osrf_prefork_run(appname);
        
-                                       osrfLogDebug( OSRF_LOG_MARK, "Server exiting for app %s and library %s", appname, libfile );
+                                       osrfLogDebug( OSRF_LOG_MARK, "Server exiting for app %s and library %s\n", appname, libfile );
                                        exit(0);
                                }
                        } // language == c
@@ -128,16 +137,28 @@ int osrfSystemBootstrap( char* hostname, char* configfile, char* contextNode ) {
 
        /* background and let our children do their thing */
        daemonize();
-       while(1) {
-               signal(SIGCHLD, __osrfSystemSignalHandler);
-               sleep(10000);
-       }
-       
+    while(1) {
+        errno = 0;
+        pid_t pid = wait(NULL);
+        if(-1 == pid) {
+            if(errno == ECHILD)
+                osrfLogError(OSRF_LOG_MARK, "We have no more live services... exiting");
+            else
+                osrfLogError(OSRF_LOG_MARK, "Exiting top-level system loop with error: %s", strerror(errno));
+            break;
+        } else {
+            osrfLogError(OSRF_LOG_MARK, "We lost a top-level service process with PID %ld", pid);
+        }
+    }
+
+
        return 0;
 }
 
 int osrf_system_bootstrap_client_resc( char* config_file, char* contextnode, char* resource ) {
 
+       int failure = 0;
+
        if(osrfSystemGetTransportClient()) {
                osrfLogInfo(OSRF_LOG_MARK, "Client is already bootstrapped");
                return 1; /* we already have a client connection */
@@ -149,39 +170,50 @@ int osrf_system_bootstrap_client_resc( char* config_file, char* contextnode, cha
        }
 
        if( config_file ) {
-               osrfConfigCleanup();
                osrfConfig* cfg = osrfConfigInit( config_file, contextnode );
-               osrfConfigSetDefaultConfig(cfg);
+               if(cfg)
+                       osrfConfigSetDefaultConfig(cfg);
+               else
+                       return 0;   /* Can't load configuration?  Bail out */
        }
 
 
        char* log_file          = osrfConfigGetValue( NULL, "/logfile");
-       char* log_level = osrfConfigGetValue( NULL, "/loglevel" );
-       osrfStringArray* arr = osrfNewStringArray(8);
+       char* log_level         = osrfConfigGetValue( NULL, "/loglevel" );
+       osrfStringArray* arr    = osrfNewStringArray(8);
        osrfConfigGetValueList(NULL, arr, "/domains/domain");
+
        char* username          = osrfConfigGetValue( NULL, "/username" );
        char* password          = osrfConfigGetValue( NULL, "/passwd" );
-       char* port                      = osrfConfigGetValue( NULL, "/port" );
+       char* port              = osrfConfigGetValue( NULL, "/port" );
        char* unixpath          = osrfConfigGetValue( NULL, "/unixpath" );
        char* facility          = osrfConfigGetValue( NULL, "/syslog" );
        char* actlog            = osrfConfigGetValue( NULL, "/actlog" );
 
-       char* domain = strdup(osrfStringArrayGetString( arr, 0 )); /* just the first for now */
-       osrfStringArrayFree(arr);
+       if(!log_file) {
+               fprintf(stderr, "No log file specified in configuration file %s\n",
+                          config_file);
+               free(log_level);
+               free(username);
+               free(password);
+               free(port);
+               free(unixpath);
+               free(facility);
+               free(actlog);
+               return -1;
+       }
 
-   /* if we're a source-client, tell the logger */
-   char* isclient = osrfConfigGetValue(NULL, "/client");
-   if( isclient && !strcasecmp(isclient,"true") )
-      osrfLogSetIsClient(1);
-   free(isclient);
+       /* if we're a source-client, tell the logger */
+       char* isclient = osrfConfigGetValue(NULL, "/client");
+       if( isclient && !strcasecmp(isclient,"true") )
+               osrfLogSetIsClient(1);
+       free(isclient);
 
        int llevel = 0;
        int iport = 0;
        if(port) iport = atoi(port);
        if(log_level) llevel = atoi(log_level);
 
-       if(!log_file) { fprintf(stderr, "Log file needed\n"); return -1; }
-
        if(!strcmp(log_file, "syslog")) {
                osrfLogInit( OSRF_LOG_TYPE_SYSLOG, contextnode, llevel );
                osrfLogSetSyslogFacility(osrfLogFacilityToInt(facility));
@@ -192,15 +224,55 @@ int osrf_system_bootstrap_client_resc( char* config_file, char* contextnode, cha
                osrfLogSetFile( log_file );
        }
 
-       osrfLogInfo( OSRF_LOG_MARK, "Bootstrapping system with domain %s, port %d, and unixpath %s", domain, iport, unixpath );
 
+       /* Get a domain, if one is specified */
+       const char* domain = osrfStringArrayGetString( arr, 0 ); /* just the first for now */
+       if(!domain) {
+               fprintf(stderr, "No domain specified in configuration file %s\n", config_file);
+               osrfLogError( OSRF_LOG_MARK, "No domain specified in configuration file %s\n", config_file);
+               failure = 1;
+       }
+
+       if(!username) {
+               fprintf(stderr, "No username specified in configuration file %s\n", config_file);
+               osrfLogError( OSRF_LOG_MARK, "No username specified in configuration file %s\n", config_file);
+               failure = 1;
+       }
+
+       if(!password) {
+               fprintf(stderr, "No password specified in configuration file %s\n", config_file);
+               osrfLogError( OSRF_LOG_MARK, "No password specified in configuration file %s\n", config_file);
+               failure = 1;
+       }
+
+       if((iport <= 0) && !unixpath) {
+               fprintf(stderr, "No unixpath or valid port in configuration file %s\n", config_file);
+               osrfLogError( OSRF_LOG_MARK, "No unixpath or valid port in configuration file %s\n",
+                       config_file);
+               failure = 1;
+       }
+
+       if (failure) {
+               osrfStringArrayFree(arr);
+               free(log_level);
+               free(username);
+               free(password);
+               free(port);
+               free(unixpath);
+               free(facility);
+               free(actlog);
+               return 0;
+       }
+
+       osrfLogInfo( OSRF_LOG_MARK, "Bootstrapping system with domain %s, port %d, and unixpath %s",
+               domain, iport, unixpath ? unixpath : "(none)" );
        transport_client* client = client_init( domain, iport, unixpath, 0 );
 
-       char* host;
+       const char* host;
        host = getenv("HOSTNAME");
 
        char tbuf[32];
-       memset(tbuf, 0x0, 32);
+       tbuf[0] = '\0';
        snprintf(tbuf, 32, "%f", get_timestamp_millis());
 
        if(!host) host = "";
@@ -208,15 +280,16 @@ int osrf_system_bootstrap_client_resc( char* config_file, char* contextnode, cha
 
        int len = strlen(resource) + 256;
        char buf[len];
-       memset(buf,0,len);
-       snprintf(buf, len - 1, "%s_%s_%s_%d", resource, host, tbuf, getpid() );
-       
+       buf[0] = '\0';
+       snprintf(buf, len - 1, "%s_%s_%s_%ld", resource, host, tbuf, (long) getpid() );
+
        if(client_connect( client, username, password, buf, 10, AUTH_DIGEST )) {
                /* child nodes will leak the parents client... but we can't free
                        it without disconnecting the parents client :( */
-               __osrfGlobalTransportClient = client;
+               osrfGlobalTransportClient = client;
        }
 
+       osrfStringArrayFree(arr);
        free(actlog);
        free(facility);
        free(log_level);
@@ -225,22 +298,21 @@ int osrf_system_bootstrap_client_resc( char* config_file, char* contextnode, cha
        free(password);
        free(port);     
        free(unixpath);
-       free(domain);
 
-       if(__osrfGlobalTransportClient)
+       if(osrfGlobalTransportClient)
                return 1;
 
        return 0;
 }
 
-int osrf_system_disconnect_client() {
-       client_disconnect( __osrfGlobalTransportClient );
-       client_free( __osrfGlobalTransportClient );
-       __osrfGlobalTransportClient = NULL;
+int osrf_system_disconnect_client( void ) {
+       client_disconnect( osrfGlobalTransportClient );
+       client_free( osrfGlobalTransportClient );
+       osrfGlobalTransportClient = NULL;
        return 0;
 }
 
-int osrf_system_shutdown() {
+int osrf_system_shutdown( void ) {
        osrfConfigCleanup();
        osrf_system_disconnect_client();
        osrf_settings_free_host_config(NULL);
@@ -252,16 +324,3 @@ int osrf_system_shutdown() {
 
 
 
-void __osrfSystemSignalHandler( int sig ) {
-
-       pid_t pid;
-       int status;
-
-       while( (pid = waitpid(-1, &status, WNOHANG)) > 0) {
-               osrfLogWarning( OSRF_LOG_MARK, "We lost child %d", pid);
-       }
-
-       /** relaunch the server **/
-}
-
-
index bc2e456..3a87008 100644 (file)
@@ -38,14 +38,12 @@ int osrf_system_bootstrap_client_resc( char* config_file, char* contextnode, cha
   */
 int osrfSystemBootstrap( char* hostName, char* configfile, char* contextNode );
 
-transport_client* osrfSystemGetTransportClient();
-transport_client* osrf_system_get_transport_client();
+transport_client* osrfSystemGetTransportClient( void );
+transport_client* osrf_system_get_transport_client( void );
 
 /* disconnects and destroys the current client connection */
 int osrf_system_disconnect_client();
-int osrf_system_shutdown(); 
-
-int _osrfSystemInitCache();
+int osrf_system_shutdown( void ); 
 
 
 /* this will clear the global transport client pointer without
index d2178eb..d7fa9a1 100644 (file)
@@ -29,7 +29,7 @@ int main( int argc, char** argv ) {
        if( (pid=fork()) ) { /* parent */
 
                signal(SIGINT, sig_int);
-               fprintf(stderr, "Listener: %d\n", getpid() );   
+               fprintf(stderr, "Listener: %ld\n", (long) getpid() );   
                char buf[300];
                memset(buf, 0, 300);
                printf("=> ");
@@ -56,7 +56,7 @@ int main( int argc, char** argv ) {
 
        } else {
 
-               fprintf(stderr, "Sender: %d\n", getpid() );     
+               fprintf(stderr, "Sender: %ld\n", (long) getpid() );     
 
                transport_message* recv;
                while( (recv=client_recv( client, -1)) ) {
index 32e3920..a318127 100644 (file)
@@ -45,19 +45,24 @@ int main( int argc, char** argv ) {
 */
 
 
-transport_client* client_init( char* server, int port, char* unix_path, int component ) {
+transport_client* client_init( const char* server, int port, const char* unix_path, int component ) {
 
        if(server == NULL) return NULL;
 
        /* build and clear the client object */
        size_t c_size = sizeof( transport_client);
-       transport_client* client = (transport_client*) safe_malloc( c_size );
+       transport_client* client = safe_malloc( c_size );
 
        /* build and clear the message list */
        size_t l_size = sizeof( transport_message_list );
-       client->m_list = (transport_message_list*) safe_malloc( l_size );
+       client->m_list = safe_malloc( l_size );
 
+       client->m_list->next = NULL;
+       client->m_list->message = NULL;
        client->m_list->type = MESSAGE_LIST_HEAD;
+
+       /* build the session */
+       
        client->session = init_transport( server, port, unix_path, client, component );
 
        client->session->message_callback = client_message_handler;
index aa0b921..50a2c66 100644 (file)
@@ -42,7 +42,7 @@ typedef struct transport_client_struct transport_client;
 // if port > 0 => connect via TCP
 // else if unix_path != NULL => connect via UNIX socket
 // ---------------------------------------------------------------------------
-transport_client* client_init( char* server, int port, char* unix_path, int component );
+transport_client* client_init( const char* server, int port, const char* unix_path, int component );
 
 
 // ---------------------------------------------------------------------------
index 1db881a..42958b3 100644 (file)
@@ -6,8 +6,8 @@
 // returns a built and allocated transport_session object.
 // This codes does no network activity, only memory initilization
 // ---------------------------------------------------------------------------------
-transport_session* init_transport(  char* server, 
-       int port, char* unix_path, void* user_data, int component ) {
+transport_session* init_transport(  const char* server, 
+       int port, const char* unix_path, void* user_data, int component ) {
 
        /* create the session struct */
        transport_session* session = 
@@ -119,7 +119,7 @@ int session_wait( transport_session* session, int timeout ) {
        int ret =  socket_wait( session->sock_mgr, timeout, session->sock_id );
 
        if( ret ) {
-               osrfLogWarning(OSRF_LOG_MARK, "socket_wait returned error code %d", ret);
+               osrfLogDebug(OSRF_LOG_MARK, "socket_wait returned error code %d", ret);
                session->state_machine->connected = 0;
        }
        return ret;
@@ -171,6 +171,10 @@ int session_connect( transport_session* session,
                                session->sock_mgr, session->unix_path)) <= 0 ) 
                        return 0;
                }
+               else {
+                       osrfLogWarning( OSRF_LOG_MARK, "Can't open session: no port or unix path" );
+                       return 0;
+               }
        }
 
        if( session->component ) {
index ba02e5b..78d108b 100644 (file)
@@ -186,8 +186,8 @@ typedef struct transport_session_struct transport_session;
 // If port > 0, then this session uses  TCP connection.  Otherwise,
 // if unix_path != NULL, it uses a UNIX domain socket.
 // ------------------------------------------------------------------
-transport_session* init_transport( char* server, int port, 
-       char* unix_path, void* user_data, int component );
+transport_session* init_transport( const char* server, int port, 
+       const char* unix_path, void* user_data, int component );
 
 // ------------------------------------------------------------------
 // Returns the value of the given XML attribute
index 47b5a4f..5998150 100644 (file)
@@ -5,7 +5,7 @@
 /* the JSON parser, so we can read the response we're XMLizing */
 #include "object.h"
 #include "json_parser.h"
-#include "utils.h"
+#include "opensrf/utils.h"
 
 char* jsonObjectToXML(jsonObject*);
 
index 32b6298..f6d9803 100644 (file)
@@ -24,7 +24,7 @@ GNU General Public License for more details.
 
 #include <stdio.h>
 #include "object.h"
-#include "utils.h"
+#include "opensrf/utils.h"
 
 
 
index baa63e9..d782574 100644 (file)
@@ -26,7 +26,7 @@ GNU General Public License for more details.
 #include <stdlib.h>
 #include <string.h>
 
-#include "utils.h"
+#include "opensrf/utils.h"
 
 /* json object types */
 #define JSON_HASH      0
index 359c255..8e9c398 100755 (executable)
@@ -40,7 +40,7 @@ sub new {
                }
 
                my ($protokey,$value,$keytype,$key);
-               if ($line =~ /^([^=\s]+)\s*=\s*(.*)/s) {
+               if ($line =~ /^([^=\s]+)\s*=\s*(.*)\s*$/s) {
                        ($protokey,$value) = ($1,$2);
                        ($keytype,$key) = split(/:/,$protokey);
                }
@@ -421,11 +421,11 @@ sub load_config {
 
 =head1 BUGS
 
-No know bugs, but report any to miker@purplefrog.com.
+No know bugs, but report any to mrylander@gmail.com.
 
 =head1 COPYRIGHT AND LICENSING
 
-Mike Rylander, Copyright 2000-2004
+Mike Rylander, Copyright 2000-2007
 
 The OpenSRF::Utils::Config module is free software. You may distribute under the terms
 of the GNU General Public License version 2 or greater.
diff --git a/src/ports/strn_compat/Makefile b/src/ports/strn_compat/Makefile
new file mode 100644 (file)
index 0000000..1398045
--- /dev/null
@@ -0,0 +1,20 @@
+# OSRF_LOG_PARAMS log all incoming method params at OSRF_INFO log level. 
+# OSRF_STRICT_PARAMS instructs the app handler to return an error if the number of method arguments
+#      provided to any method is not at least as large as the 'argc' setting for the method
+
+CFLAGS +=  -rdynamic -fno-strict-aliasing -fPIC
+
+TARGETS = strndup.o strnlen.o
+HEADERS = strndup.h strnlen.h
+
+all: libfreebsd_str_compat.so $(TARGETS)
+
+libfreebsd_str_compat.so: $(TARGETS)
+       $(CC) -shared -W1 $(TARGETS) -o $@
+
+strndup.o:     strndup.c strndup.h
+strnlen.o:     strnlen.c strnlen.h
+
+clean:
+       /bin/rm -f *o
+
diff --git a/src/ports/strn_compat/strndup.c b/src/ports/strn_compat/strndup.c
new file mode 100644 (file)
index 0000000..10b49fd
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2007 Albert Lee <trisk at acm.jhu.edu>.
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "strnlen.h"
+
+char *
+strndup(const char *s, size_t n)
+{
+       char *ns;
+
+       n = strnlen(s, n);
+
+       if ((ns = (char *)malloc(n + 1))) {
+               ns[n] = '\0';
+               return memcpy(ns, s, n);
+       }
+
+       return NULL;
+}
diff --git a/src/ports/strn_compat/strndup.h b/src/ports/strn_compat/strndup.h
new file mode 100644 (file)
index 0000000..be91f5f
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2007 Albert Lee <trisk at acm.jhu.edu>.
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+char   *strndup(const char *s, size_t n);
+
diff --git a/src/ports/strn_compat/strnlen.c b/src/ports/strn_compat/strnlen.c
new file mode 100644 (file)
index 0000000..81a6f17
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2007 The Akuma Project
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * $Id$
+ */
+
+/*
+ * sys/types.h is a Single Unix Specification header and defines size_t.
+ */
+
+#include <sys/types.h>
+
+/*
+ * As per the Linux manual page:
+ *
+ * The strnlen() function returns the number of characters in the string
+ * pointed to by s, not including the terminating '\0' character, but at most
+ * maxlen. In doing this, strnlen() looks only at the first maxlen characters
+ * at s and never beyond s+maxlen.
+ *
+ * The strnlen() function returns strlen(s), if that is less than maxlen, or
+ * maxlen if there is no '\0' character among the first maxlen characters
+ * pointed to by s.
+ */
+
+size_t
+strnlen(const char *string, size_t maxlen)
+{
+       int len = 0;
+
+       if (maxlen == 0)
+               return (0);
+
+       while (*string++ && ++len < maxlen)
+               ;
+
+       return (len);
+}
diff --git a/src/ports/strn_compat/strnlen.h b/src/ports/strn_compat/strnlen.h
new file mode 100644 (file)
index 0000000..181780a
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2007 The Akuma Project
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * $Id$
+ */
+
+size_t strnlen(const char *, size_t);
+
diff --git a/src/python/osrf/gateway.py b/src/python/osrf/gateway.py
new file mode 100644 (file)
index 0000000..3a6efaf
--- /dev/null
@@ -0,0 +1,136 @@
+from xml.dom import minidom
+from xml.sax import handler, make_parser, saxutils
+from json import *
+from net_obj import *
+import urllib, urllib2, sys
+
+defaultHost = None
+
+class GatewayRequest:
+    def __init__(self, service, method, params=[]):
+        self.service = service
+        self.method = method
+        self.params = params
+
+    def send(self):
+        params = self.buildPOSTParams()
+        request = urllib2.Request(self.buildURL(), data=params)
+        response = None
+        try:
+            response =urllib2.urlopen(request)
+        except urllib2.HTTPError, e:
+            # log this?
+            sys.stderr.write('HTTPError: code=%d : %s' % (e.code, str(e)))
+            raise e
+            
+        return self.handleResponse(response)
+
+    def buildPOSTParams(self):
+
+        params = urllib.urlencode({   
+            'service': self.service,
+            'method': self.method,
+            'format': self.getFormat()
+        })
+
+        for p in self.params:
+            param = {'param': osrfObjectToJSON(p)}
+            params += '&%s' % urllib.urlencode(param)
+
+        return params
+
+    def setDefaultHost(host):
+        global defaultHost
+        defaultHost = host
+    setDefaultHost = staticmethod(setDefaultHost)
+
+    def buildURL(self):
+        return 'http://%s/gateway' % defaultHost
+
+
+class XMLGatewayRequest(GatewayRequest):
+
+    def __init__(self, service, method, *params):
+        GatewayRequest.__init__(self, service, method, list(params))
+
+    def getFormat(self):
+        return 'xml'
+
+    def handleResponse(self, response):
+        handler = XMLGatewayParser()
+        parser = make_parser()
+        parser.setContentHandler(handler)
+        parser.parse(response)
+        return handler.getResult()
+
+class XMLGatewayParser(handler.ContentHandler):
+
+    def __init__(self):
+        self.result = None
+        self.objStack = []
+        self.keyStack = []
+
+    def getResult(self):
+        return self.result
+
+    def __getAttr(self, attrs, name):
+        for (k, v) in attrs.items():
+            if k == name:
+                return v
+        return None
+
+    def startElement(self, name, attrs):
+
+        # XXX add support for serializable objects!
+
+        if name == 'element': # this is an object item wrapper
+            self.keyStack.append(self.__getAttr(attrs, 'key'))
+            return
+
+        if name == 'object':
+            obj = {}
+            self.appendChild(obj)
+            self.objStack.append(obj)
+            return
+
+        if name == 'array':
+            obj = []
+            self.appendChild(obj)
+            self.objStack.append(obj)
+            return
+
+        if name == 'null':
+            self.appendChild(None)
+            return
+
+        if name == 'boolean':
+            self.appendChild((self.__getAttr(attrs, 'value') == 'true'))
+            return
+
+
+    def appendChild(self, child):
+
+        if self.result == None:
+            self.result = child
+
+        if not self.objStack: return;
+
+        parent = self.objStack[len(self.objStack)-1]
+
+        if( isinstance(parent, list) ):
+            parent.append(child)
+        else:
+            parent[self.keyStack.pop()] = child
+
+    def endElement(self, name):
+        if name == 'array' or name == 'object':
+            self.objStack.pop()
+
+    def characters(self, chars):
+        #self.appendChild(''.join(chars[start:leng+start]))
+        self.appendChild(urllib.unquote_plus(chars))
+
+
+
+    
+
index 826e6b9..1b73e37 100644 (file)
 # -----------------------------------------------------------------------
 
 
-import simplejson, types, cjson
+import simplejson, types 
+from osrf.net_obj import *
 
 JSON_PAYLOAD_KEY = '__p'
 JSON_CLASS_KEY = '__c'
 
-class osrfNetworkObject(object):
-    """Base class for serializable network objects."""
-    def getData(self):
-        """Returns a dict of data contained by this object"""
-        return self.data
-
-
-class __unknown(osrfNetworkObject):
-    """Default class for un-registered network objects."""
-    def __init__(self, data=None):
-        self.data = data
-
-setattr(__unknown,'__keys', [])
-setattr(osrfNetworkObject,'__unknown', __unknown)
-
-
-def osrfNetworkRegisterHint(hint, keys, type='hash'):
-    """Register a network hint.  
-    
-        This creates a new class at osrfNetworkObject.<hint> with 
-        methods for accessing/mutating the object's data.  
-        Method names will match the names found in the keys array
-
-        hint - The hint name to encode with the object
-        type - The data container type.  
-        keys - An array of data keys.  If type is an 'array', the order of
-        the keys will determine how the data is accessed
-    """
-
-    # XXX there must be a cleaner way to do this via the python API
-
-    estr = "class %s(osrfNetworkObject):\n" % hint
-    estr += "\tdef __init__(self, data=None):\n"
-    estr += "\t\tself.data = data\n"
-    estr += "\t\tif data:\n"
-
-    if type == 'hash': 
-        estr += "\t\t\tpass\n"
-    else:
-        # we have to make sure the array is large enough    
-        estr += "\t\t\twhile len(data) < %d:\n" % len(keys)
-        estr += "\t\t\t\tdata.append(None)\n"
-
-    estr += "\t\telse:\n"
-
-    if type == 'array':
-        estr += "\t\t\tself.data = []\n"
-        estr += "\t\t\tfor i in range(%s):\n" % len(keys)
-        estr += "\t\t\t\tself.data.append(None)\n"
-        for i in range(len(keys)):
-            estr += "\tdef %s(self, *args):\n"\
-                        "\t\tif len(args) != 0:\n"\
-                        "\t\t\tself.data[%s] = args[0]\n"\
-                        "\t\treturn self.data[%s]\n" % (keys[i], i, i)
-
-    if type == 'hash':
-        estr += "\t\t\tself.data = {}\n"
-        estr += "\t\t\tfor i in %s:\n" % str(keys)
-        estr += "\t\t\t\tself.data[i] = None\n"
-        for i in keys:
-            estr += "\tdef %s(self, *args):\n"\
-                        "\t\tif len(args) != 0:\n"\
-                        "\t\t\tself.data['%s'] = args[0]\n"\
-                        "\t\tval = None\n"\
-                        "\t\ttry: val = self.data['%s']\n"\
-                        "\t\texcept: return None\n"\
-                        "\t\treturn val\n" % (i, i, i)
-
-    estr += "setattr(osrfNetworkObject, '%s', %s)\n" % (hint,hint)
-    estr += "setattr(osrfNetworkObject.%s, '__keys', keys)" % hint
-    exec(estr)
-    
-        
-
-# -------------------------------------------------------------------
-# Define the custom object parsing behavior 
-# -------------------------------------------------------------------
-def __parseNetObject(obj):
-    hint = None
-    #islist = False
-    try:
-        hint = obj[JSON_CLASS_KEY]
-        obj = obj[JSON_PAYLOAD_KEY]
-    except: pass
-    if isinstance(obj,list):
-        #islist = True
-        for i in range(len(obj)):
-            obj[i] = __parseNetObject(obj[i])
-    else: 
-        if isinstance(obj,dict):
-            for k,v in obj.iteritems():
-                obj[k] = __parseNetObject(v)
-
-    if hint: # Now, "bless" the object into an osrfNetworkObject
-        estr = 'obj = osrfNetworkObject.%s(obj)' % hint
-        try:
-            exec(estr)
-        except AttributeError:
-            # this object has not been registered, shove it into the default container
-            obj = osrfNetworkObject.__unknown(obj)
-
-    return obj;
-
-
-# -------------------------------------------------------------------
+#class osrfNetworkObject(object):
+#      """Base class for serializable network objects."""
+#      def getData(self):
+#              """Returns a dict of data contained by this object"""
+#              return self.data
+#
+#
+#class __unknown(osrfNetworkObject):
+#      """Default class for un-registered network objects."""
+#      def __init__(self, data=None):
+#              self.data = data
+#
+#setattr(__unknown,'__keys', [])
+#setattr(osrfNetworkObject,'__unknown', __unknown)
+#
+#
+#def osrfNetworkRegisterHint(hint, keys, type='hash'):
+#      """Register a network hint.  
+#      
+#              This creates a new class at osrfNetworkObject.<hint> with 
+#              methods for accessing/mutating the object's data.  
+#              Method names will match the names found in the keys array
+#
+#              hint - The hint name to encode with the object
+#              type - The data container type.  
+#              keys - An array of data keys.  If type is an 'array', the order of
+#              the keys will determine how the data is accessed
+#      """
+#
+#      estr = "class %s(osrfNetworkObject):\n" % hint
+#      estr += "\tdef __init__(self, data=None):\n"
+#      estr += "\t\tself.data = data\n"
+#      estr += "\t\tif data:\n"
+#
+#      if type == 'hash': 
+#              estr += "\t\t\tpass\n"
+#      else:
+#              # we have to make sure the array is large enough        
+#              estr += "\t\t\twhile len(data) < %d:\n" % len(keys)
+#              estr += "\t\t\t\tdata.append(None)\n"
+#
+#      estr += "\t\telse:\n"
+#
+#      if type == 'array':
+#              estr += "\t\t\tself.data = []\n"
+#              estr += "\t\t\tfor i in range(%s):\n" % len(keys)
+#              estr += "\t\t\t\tself.data.append(None)\n"
+#              for i in range(len(keys)):
+#                      estr += "\tdef %s(self, *args):\n"\
+#                                              "\t\tif len(args) != 0:\n"\
+#                                              "\t\t\tself.data[%s] = args[0]\n"\
+#                                              "\t\treturn self.data[%s]\n" % (keys[i], i, i)
+#
+#      if type == 'hash':
+#              estr += "\t\t\tself.data = {}\n"
+#              estr += "\t\t\tfor i in %s:\n" % str(keys)
+#              estr += "\t\t\t\tself.data[i] = None\n"
+#              for i in keys:
+#                      estr += "\tdef %s(self, *args):\n"\
+#                                              "\t\tif len(args) != 0:\n"\
+#                                              "\t\t\tself.data['%s'] = args[0]\n"\
+#                                              "\t\tval = None\n"\
+#                                              "\t\ttry: val = self.data['%s']\n"\
+#                                              "\t\texcept: return None\n"\
+#                                              "\t\treturn val\n" % (i, i, i)
+#
+#      estr += "setattr(osrfNetworkObject, '%s', %s)\n" % (hint,hint)
+#      estr += "setattr(osrfNetworkObject.%s, '__keys', keys)" % hint
+#      exec(estr)
+#      
+#              
+#
+## -------------------------------------------------------------------
+## Define the custom object parsing behavior 
+## -------------------------------------------------------------------
+#def __parseNetObject(obj):
+#      hint = None
+#      islist = False
+#      try:
+#              hint = obj[JSON_CLASS_KEY]
+#              obj = obj[JSON_PAYLOAD_KEY]
+#      except: pass
+#      if isinstance(obj,list):
+#              islist = True
+#              for i in range(len(obj)):
+#                      obj[i] = __parseNetObject(obj[i])
+#      else: 
+#              if isinstance(obj,dict):
+#                      for k,v in obj.iteritems():
+#                              obj[k] = __parseNetObject(v)
+#
+#      if hint: # Now, "bless" the object into an osrfNetworkObject
+#              estr = 'obj = osrfNetworkObject.%s(obj)' % hint
+#              try:
+#                      exec(estr)
+#              except AttributeError:
+#                      # this object has not been registered, shove it into the default container
+#                      obj = osrfNetworkObject.__unknown(obj)
+#
+#      return obj;
+#
+#
+## -------------------------------------------------------------------
 # Define the custom object encoding behavior 
 # -------------------------------------------------------------------
+
 class osrfJSONNetworkEncoder(simplejson.JSONEncoder):
-    def default(self, obj):
-        if isinstance(obj, osrfNetworkObject):
-            return { 
-                JSON_CLASS_KEY: obj.__class__.__name__,
-                JSON_PAYLOAD_KEY: self.default(obj.getData())
-            }   
-        return obj
+       def default(self, obj):
+               if isinstance(obj, osrfNetworkObject):
+                       return { 
+                               JSON_CLASS_KEY: obj.__class__.__name__,
+                               JSON_PAYLOAD_KEY: self.default(obj.getData())
+                       }       
+               return obj
 
 
 def osrfObjectToJSON(obj):
-    """Turns a python object into a wrapped JSON object"""
-    return simplejson.dumps(obj, cls=osrfJSONNetworkEncoder)
+       """Turns a python object into a wrapped JSON object"""
+       return simplejson.dumps(obj, cls=osrfJSONNetworkEncoder)
 
 
 def osrfJSONToObject(json):
-    """Turns a JSON string into python objects"""
-    #obj = simplejson.loads(json)
-    obj = None
-    try:
-        obj = cjson.decode(json)
-    except Exception:
-        # cjson is more finicky, if it dies, try simplejson
-        obj = simplejson.loads(json)
-    return __parseNetObject(obj)
+       """Turns a JSON string into python objects"""
+       obj = simplejson.loads(json)
+       return parseNetObject(obj)
 
 def osrfParseJSONRaw(json):
-    """Parses JSON the old fashioned way."""
-    return simplejson.loads(json)
+       """Parses JSON the old fashioned way."""
+       return simplejson.loads(json)
 
 def osrfToJSONRaw(obj):
-    """Stringifies an object as JSON with no additional logic."""
-    return simplejson.dumps(obj)
+       """Stringifies an object as JSON with no additional logic."""
+       return simplejson.dumps(obj)
 
 def __tabs(t):
-    r=''
-    for i in range(t): r += '   '
-    return r
+       r=''
+       for i in range(t): r += '   '
+       return r
 
-def osrfDebugNetworkObject(obj, t=0):
-    """Returns a debug string for a given object.
+def osrfDebugNetworkObject(obj, t=1):
+       """Returns a debug string for a given object.
 
-    If it's an osrfNetworkObject and has registered keys, key/value p
-    pairs are returned.  Otherwise formatted JSON is returned"""
+       If it's an osrfNetworkObject and has registered keys, key/value p
+       pairs are returned.  Otherwise formatted JSON is returned"""
 
-    s = ''
-    if isinstance(obj, osrfNetworkObject) and len(obj.__keys):
-        obj.__keys.sort()
+       s = ''
+       if isinstance(obj, osrfNetworkObject) and len(obj.__keys):
+               obj.__keys.sort()
 
-        for k in obj.__keys:
+               for k in obj.__keys:
 
-            key = k
-            while len(key) < 24: key += '.' # pad the names to make the values line up somewhat
-            val = getattr(obj, k)()
+                       key = k
+                       while len(key) < 24: key += '.' # pad the names to make the values line up somewhat
+                       val = getattr(obj, k)()
 
-            subobj = val and not (isinstance(val,unicode) or isinstance(val,str) or\
-                    isinstance(val, int) or isinstance(val, float) or isinstance(val, long))
+                       subobj = val and not (isinstance(val,unicode) or \
+                                       isinstance(val, int) or isinstance(val, float) or isinstance(val, long))
 
 
-            s += __tabs(t) + key + ' '
+                       s += __tabs(t) + key + ' = '
 
-            if subobj:
-                s += '\n'
-                val = osrfDebugNetworkObject(val, t+1)
+                       if subobj:
+                               s += '\n'
+                               val = osrfDebugNetworkObject(val, t+1)
 
-            s += str(val)
+                       s += str(val)
 
-            if not subobj: s += '\n'
+                       if not subobj: s += '\n'
 
-    else:
-        s = osrfFormatJSON(osrfObjectToJSON(obj))
-    return s
+       else:
+               s = osrfFormatJSON(osrfObjectToJSON(obj))
+       return s
 
 def osrfFormatJSON(json):
-    """JSON pretty-printer"""
-    r = ''
-    t = 0
-    instring = False
-    inescape = False
-    done = False
+       """JSON pretty-printer"""
+       r = ''
+       t = 0
+       instring = False
+       inescape = False
+       done = False
 
-    for c in json:
+       for c in json:
 
-        done = False
-        if (c == '{' or c == '[') and not instring:
-            t += 1
-            r += c + '\n' + __tabs(t)
-            done = True
+               done = False
+               if (c == '{' or c == '[') and not instring:
+                       t += 1
+                       r += c + '\n' + __tabs(t)
+                       done = True
 
-        if (c == '}' or c == ']') and not instring:
-            t -= 1
-            r += '\n' + __tabs(t) + c
-            done = True
+               if (c == '}' or c == ']') and not instring:
+                       t -= 1
+                       r += '\n' + __tabs(t) + c
+                       done = True
 
-        if c == ',' and not instring:
-            r += c + '\n' + __tabs(t)
-            done = True
+               if c == ',' and not instring:
+                       r += c + '\n' + __tabs(t)
+                       done = True
 
-        if c == '"' and not inescape:
-            instring = not instring
+               if c == '"' and not inescape:
+                       instring = not instring
 
-        if inescape: 
-            inescape = False
+               if inescape: 
+                       inescape = False
 
-        if c == '\\':
-            inescape = True
+               if c == '\\':
+                       inescape = True
 
-        if not done:
-            r += c
+               if not done:
+                       r += c
 
-    return r
+       return r
 
-    
+       
diff --git a/src/python/osrf/net_obj.py b/src/python/osrf/net_obj.py
new file mode 100644 (file)
index 0000000..1dafa1e
--- /dev/null
@@ -0,0 +1,127 @@
+# -----------------------------------------------------------------------
+# Copyright (C) 2007  Georgia Public Library Service
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# -----------------------------------------------------------------------
+
+
+JSON_PAYLOAD_KEY = '__p'
+JSON_CLASS_KEY = '__c'
+
+class osrfNetworkObject(object):
+       """Base class for serializable network objects."""
+       def getData(self):
+               """Returns a dict of data contained by this object"""
+               return self.data
+
+
+class __unknown(osrfNetworkObject):
+       """Default class for un-registered network objects."""
+       def __init__(self, data=None):
+               self.data = data
+
+setattr(__unknown,'__keys', [])
+setattr(osrfNetworkObject,'__unknown', __unknown)
+
+
+def osrfNetworkRegisterHint(hint, keys, type='hash'):
+       """Register a network hint.  
+       
+               This creates a new class at osrfNetworkObject.<hint> with 
+               methods for accessing/mutating the object's data.  
+               Method names will match the names found in the keys array
+
+               hint - The hint name to encode with the object
+               type - The data container type.  
+               keys - An array of data keys.  If type is an 'array', the order of
+               the keys will determine how the data is accessed
+       """
+
+    #
+    # XXX Surely there is a cleaner way to accomplish this via 
+    # the PythonAPI
+    #
+
+       estr = "class %s(osrfNetworkObject):\n" % hint
+       estr += "\tdef __init__(self, data=None):\n"
+       estr += "\t\tself.data = data\n"
+       estr += "\t\tif data:\n"
+
+       if type == 'hash': 
+               estr += "\t\t\tpass\n"
+       else:
+               # we have to make sure the array is large enough        
+               estr += "\t\t\twhile len(data) < %d:\n" % len(keys)
+               estr += "\t\t\t\tdata.append(None)\n"
+
+       estr += "\t\telse:\n"
+
+       if type == 'array':
+               estr += "\t\t\tself.data = []\n"
+               estr += "\t\t\tfor i in range(%s):\n" % len(keys)
+               estr += "\t\t\t\tself.data.append(None)\n"
+               for i in range(len(keys)):
+                       estr += "\tdef %s(self, *args):\n"\
+                                               "\t\tif len(args) != 0:\n"\
+                                               "\t\t\tself.data[%s] = args[0]\n"\
+                                               "\t\treturn self.data[%s]\n" % (keys[i], i, i)
+
+       if type == 'hash':
+               estr += "\t\t\tself.data = {}\n"
+               estr += "\t\t\tfor i in %s:\n" % str(keys)
+               estr += "\t\t\t\tself.data[i] = None\n"
+               for i in keys:
+                       estr += "\tdef %s(self, *args):\n"\
+                                               "\t\tif len(args) != 0:\n"\
+                                               "\t\t\tself.data['%s'] = args[0]\n"\
+                                               "\t\tval = None\n"\
+                                               "\t\ttry: val = self.data['%s']\n"\
+                                               "\t\texcept: return None\n"\
+                                               "\t\treturn val\n" % (i, i, i)
+
+       estr += "setattr(osrfNetworkObject, '%s', %s)\n" % (hint,hint)
+       estr += "setattr(osrfNetworkObject.%s, '__keys', keys)" % hint
+       exec(estr)
+       
+               
+
+# -------------------------------------------------------------------
+# Define the custom object parsing behavior 
+# -------------------------------------------------------------------
+def parseNetObject(obj):
+       hint = None
+       islist = False
+       try:
+               hint = obj[JSON_CLASS_KEY]
+               obj = obj[JSON_PAYLOAD_KEY]
+       except: pass
+       if isinstance(obj,list):
+               islist = True
+               for i in range(len(obj)):
+                       obj[i] = parseNetObject(obj[i])
+       else: 
+               if isinstance(obj,dict):
+                       for k,v in obj.iteritems():
+                               obj[k] = parseNetObject(v)
+
+       if hint: # Now, "bless" the object into an osrfNetworkObject
+               estr = 'obj = osrfNetworkObject.%s(obj)' % hint
+               try:
+                       exec(estr)
+               except AttributeError:
+                       # this object has not been registered, shove it into the default container
+                       obj = osrfNetworkObject.__unknown(obj)
+
+       return obj;
+
+
+
+       
index 2fbb502..f1c6c38 100644 (file)
@@ -14,6 +14,7 @@
 # -----------------------------------------------------------------------
 
 from osrf.json import *
+from osrf.net_obj import *
 from osrf.conf import osrfConfigValue
 from osrf.net import osrfNetworkMessage, osrfGetNetworkHandle
 from osrf.log import *
index 1d9d7aa..fe637f1 100644 (file)
-# -----------------------------------------------------------------------
-# Copyright (C) 2007  Georgia Public Library Service
-# Bill Erickson <billserickson@gmail.com>
-# 
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-# -----------------------------------------------------------------------
-
-import libxml2, re
+import xml.dom.minidom, re
 
 def osrfXMLFileToObject(filename):
-       """Turns the contents of an XML file into a Python object"""
-       doc     = libxml2.parseFile(filename)
-       xmlNode = doc.children.children
-       return osrfXMLNodeToObject(xmlNode)
+    """Turns the contents of an XML file into a Python object"""
+    doc = xml.dom.minidom.parse(filename)
+    obj = osrfXMLNodeToObject(doc.childNodes[0])
+    doc.unlink()
+    return obj
 
 def osrfXMLStringToObject(string):
-       """Turns an XML string into a Python object"""
-       doc     = libxml2.parseString(string)
-       xmlNode = doc.children.children
-       return osrfXMLNodeToObject(xmlNode)
+    """Turns an XML string into a Python object"""
+    doc = xml.dom.minidom.parseString(string)
+    obj = osrfXMLNodeToObject(doc.childNodes[0])
+    doc.unlink()
+    return obj
 
 def osrfXMLNodeToObject(xmlNode):
-       """Turns an XML node into a Python object"""
-       obj = {}
+    """Turns an XML node into a Python object"""
+    obj = {}
 
-       while xmlNode:
-               if xmlNode.type == 'element':
-                       nodeChild = xmlNode.children
-                       done = False
-                       nodeName = xmlNode.name
+    if xmlNode.nodeType != xmlNode.ELEMENT_NODE:
+        return obj
 
-                       while nodeChild:
-                               if nodeChild.type == 'element':
+    done = False
+    nodeName = xmlNode.nodeName
 
-                                       # If a node has element children, create a new sub-object 
-                                       # for this node, attach an array for each type of child
-                                       # and recursively collect the children data into the array(s)
+    for nodeChild in xmlNode.childNodes:
+        if nodeChild.nodeType == xmlNode.ELEMENT_NODE:
 
-                                       if not obj.has_key(nodeName):
-                                               obj[nodeName] = {}
+            # If a node has element children, create a new sub-object 
+            # for this node, attach an array for each type of child
+            # and recursively collect the children data into the array(s)
 
-                                       sub_obj = osrfXMLNodeToObject(nodeChild);
+            if not obj.has_key(nodeName):
+                obj[nodeName] = {}
 
-                                       if not obj[nodeName].has_key(nodeChild.name):
-                                               # we've encountered 1 sub-node with nodeChild's name
-                                               obj[nodeName][nodeChild.name] = sub_obj[nodeChild.name]
+            sub_obj = osrfXMLNodeToObject(nodeChild);
 
-                                       else:
-                                               if isinstance(obj[nodeName][nodeChild.name], list):
-                                                       # we already have multiple sub-nodes with nodeChild's name
-                                                       obj[nodeName][nodeChild.name].append(sub_obj[nodeChild.name])
+            if not obj[nodeName].has_key(nodeChild.nodeName):
+                # we've encountered 1 sub-node with nodeChild's name
+                obj[nodeName][nodeChild.nodeName] = sub_obj[nodeChild.nodeName]
 
-                                               else:
-                                                       # we already have 1 sub-node with nodeChild's name, make 
-                                                       # it a list and append the current node
-                                                       val = obj[nodeName][nodeChild.name]
-                                                       obj[nodeName][nodeChild.name] = [ val, sub_obj[nodeChild.name] ]
+            else:
+                if isinstance(obj[nodeName][nodeChild.nodeName], list):
+                    # we already have multiple sub-nodes with nodeChild's name
+                    obj[nodeName][nodeChild.nodeName].append(sub_obj[nodeChild.nodeName])
 
-                                       done = True
+                else:
+                    # we already have 1 sub-node with nodeChild's name, make 
+                    # it a list and append the current node
+                    val = obj[nodeName][nodeChild.nodeName]
+                    obj[nodeName][nodeChild.nodeName] = [ val, sub_obj[nodeChild.nodeName] ]
 
-                               nodeChild = nodeChild.next
+            done = True
 
-                       if not done:
-                               # If the node has no children, clean up the text content 
-                               # and use that as the data
-                               data = re.compile('^\s*').sub('', xmlNode.content)
-                               data = re.compile('\s*$').sub('', data)
+    if not done:
+        # If the node has no element children, clean up the text content 
+        # and use that as the data
+        xmlNode = xmlNode.childNodes[0] # extract the text node
+        data = re.compile('^\s*').sub('', str(xmlNode.nodeValue))
+        data = re.compile('\s*$').sub('', data)
 
-                               obj[nodeName] = data
+        obj[nodeName] = data
 
-               xmlNode = xmlNode.next
-
-       return obj
+    return obj
 
 
 def osrfObjectFindPath(obj, path, idx=None):
-       """Searches an object along the given path for a value to return.
+    """Searches an object along the given path for a value to return.
 
-       Path separaters can be '/' or '.', '/' is tried first."""
+    Path separaters can be '/' or '.', '/' is tried first."""
 
-       parts = []
+    parts = []
 
-       if re.compile('/').search(path):
-               parts = path.split('/')
-       else:
-               parts = path.split('.')
+    if re.compile('/').search(path):
+        parts = path.split('/')
+    else:
+        parts = path.split('.')
 
-       for part in parts:
-               try:
-                       o = obj[part]
-               except Exception:
-                       return None
-               if isinstance(o,str): 
-                       return o
-               if isinstance(o,list):
-                       if( idx != None ):
-                               return o[idx]
-                       return o
-               if isinstance(o,dict):
-                       obj = o
-               else:
-                       return o
+    for part in parts:
+        try:
+            o = obj[part]
+        except Exception:
+            return None
+        if isinstance(o,str): 
+            return o
+        if isinstance(o,list):
+            if( idx != None ):
+                return o[idx]
+            return o
+        if isinstance(o,dict):
+            obj = o
+        else:
+            return o
 
-       return obj
+    return obj
 
 
-                       
+            
 
index be2abe0..3adb8b1 100644 (file)
@@ -61,7 +61,7 @@ void osrfLogSetIsClient(int is) {
    /* go ahead and create the xid prefix so it will be consistent later */
    static char buff[32];
    memset(buff, 0x0, 32);
-   snprintf(buff, 32, "%d%d", (int)time(NULL), getpid());
+   snprintf(buff, 32, "%d%ld", (int)time(NULL), (long) getpid());
    __osrfLogXidPfx = buff;
 }
 
@@ -177,11 +177,11 @@ void _osrfLogDetail( int level, const char* filename, int line, char* msg ) {
                buf[1533] = '.';
                buf[1534] = '.';
                buf[1535] = '\0';
-               syslog( fac | lvl, "[%s:%d:%s:%d:%s] %s", l, getpid(), filename, line, xid, buf );
+               syslog( fac | lvl, "[%s:%ld:%s:%d:%s] %s", l, (long) getpid(), filename, line, xid, buf );
        }
 
        else if( __osrfLogType == OSRF_LOG_TYPE_FILE )
-               _osrfLogToFile("[%s:%d:%s:%d:%s] %s", l, getpid(), filename, line, xid, msg );
+               _osrfLogToFile("[%s:%ld:%s:%d:%s] %s", l, (long) getpid(), filename, line, xid, msg );
 
 }
 
@@ -205,14 +205,14 @@ void _osrfLogToFile( char* msg, ... ) {
 
        FILE* file = fopen(__osrfLogFile, "a");
        if(!file) {
-               fprintf(stderr, "Unable to fopen file %s for writing", __osrfLogFile);
+               fprintf(stderr, "Unable to fopen file %s for writing\n", __osrfLogFile);
                return;
        }
 
        fprintf(file, "%s %s %s\n", __osrfLogAppname, datebuf, VA_BUF );
        if( fclose(file) != 0 ) 
                osrfLogWarning(OSRF_LOG_MARK, "Error closing log file: %s", strerror(errno));
-       
+
 }
 
 
index 5441adf..4356ef6 100644 (file)
@@ -1,5 +1,19 @@
 #include "socket_bundle.h"
 
+/* buffer used to read from the sockets */
+#define RBUFSIZE 1024
+
+static socket_node* _socket_add_node(socket_manager* mgr,
+               int endpoint, int addr_type, int sock_fd, int parent_id );
+static socket_node* socket_find_node(socket_manager* mgr, int sock_fd);
+static void socket_remove_node(socket_manager*, int sock_fd);
+static int _socket_send(int sock_fd, const char* data, int flags);
+static int _socket_route_data(socket_manager* mgr, int num_active, fd_set* read_set);
+static int _socket_route_data_id( socket_manager* mgr, int sock_id);
+static int _socket_handle_new_client(socket_manager* mgr, socket_node* node);
+static int _socket_handle_client_data(socket_manager* mgr, socket_node* node);
+
+
 /* -------------------------------------------------------------------- 
        Test Code 
        -------------------------------------------------------------------- */
@@ -38,8 +52,9 @@ int main(int argc, char* argv[]) {
 /* -------------------------------------------------------------------- */
 
 
-
-socket_node* _socket_add_node(socket_manager* mgr, 
+/* allocates and inserts a new socket node into the nodeset.
+       if parent_id is positive and non-zero, it will be set */
+static socket_node* _socket_add_node(socket_manager* mgr, 
                int endpoint, int addr_type, int sock_fd, int parent_id ) {
 
        if(mgr == NULL) return NULL;
@@ -72,10 +87,11 @@ int socket_open_tcp_server(socket_manager* mgr, int port, char* listen_ip) {
        int sock_fd;
        struct sockaddr_in server_addr;
 
+       errno = 0;
        sock_fd = socket(AF_INET, SOCK_STREAM, 0);
-
        if(sock_fd < 0) {
-               osrfLogWarning( OSRF_LOG_MARK, "tcp_server_connect(): Unable to create socket");
+               osrfLogWarning( OSRF_LOG_MARK, "socket_open_tcp_server(): Unable to create TCP socket: %s",
+                       strerror( errno ) );
                return -1;
        }
 
@@ -89,13 +105,17 @@ int socket_open_tcp_server(socket_manager* mgr, int port, char* listen_ip) {
 
        server_addr.sin_port = htons(port);
 
+       errno = 0;
        if(bind( sock_fd, (struct sockaddr*) &server_addr, sizeof(server_addr)) < 0) {
-               osrfLogWarning( OSRF_LOG_MARK, "tcp_server_connect(): cannot bind to port %d", port );
+               osrfLogWarning( OSRF_LOG_MARK, "socket_open_tcp_server(): cannot bind to port %d: %s",
+                       port, strerror( errno ) );
                return -1;
        }
 
+       errno = 0;
        if(listen(sock_fd, 20) == -1) {
-               osrfLogWarning( OSRF_LOG_MARK, "tcp_server_connect(): listen() returned error");
+               osrfLogWarning( OSRF_LOG_MARK, "socket_open_tcp_server(): listen() returned error: %s",
+                       strerror( errno ) );
                return -1;
        }
 
@@ -110,24 +130,30 @@ int socket_open_unix_server(socket_manager* mgr, char* path) {
        int sock_fd;
        struct sockaddr_un server_addr;
 
+       errno = 0;
        sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
        if(sock_fd < 0){
-               osrfLogWarning( OSRF_LOG_MARK, "socket_open_unix_server(): socket() failed");
+               osrfLogWarning( OSRF_LOG_MARK, "socket_open_unix_server(): socket() failed: %s",
+                       strerror( errno ) );
                return -1;
        }
 
        server_addr.sun_family = AF_UNIX;
        strcpy(server_addr.sun_path, path);
 
+       errno = 0;
        if( bind(sock_fd, (struct sockaddr*) &server_addr, 
                                sizeof(struct sockaddr_un)) < 0) {
                osrfLogWarning( OSRF_LOG_MARK, 
-                       "socket_open_unix_server(): cannot bind to unix port %s", path );
+                       "socket_open_unix_server(): cannot bind to unix port %s: %s",
+                       path, strerror( errno ) );
                return -1;
        }
 
+       errno = 0;
        if(listen(sock_fd, 20) == -1) {
-               osrfLogWarning( OSRF_LOG_MARK, "socket_open_unix_server(): listen() returned error");
+               osrfLogWarning( OSRF_LOG_MARK, "socket_open_unix_server(): listen() returned error: %s",
+                       strerror( errno ) );
                return -1;
        }
 
@@ -154,8 +180,9 @@ int socket_open_udp_server(
        int sockfd;
        struct sockaddr_in server_addr;
 
+       errno = 0;
        if( (sockfd = socket( AF_INET, SOCK_DGRAM, 0 )) < 0 ) {
-               osrfLogWarning( OSRF_LOG_MARK, "Unable to create UDP socket");
+               osrfLogWarning( OSRF_LOG_MARK, "Unable to create UDP socket: %s", strerror( errno ) );
                return -1;
        }
 
@@ -164,8 +191,10 @@ int socket_open_udp_server(
        if(listen_ip) server_addr.sin_addr.s_addr = inet_addr(listen_ip);
        else server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
 
+       errno = 0;
        if( (bind (sockfd, (struct sockaddr *) &server_addr,sizeof(server_addr))) ) {
-               osrfLogWarning( OSRF_LOG_MARK, "Unable to bind to UDP port %d", port);
+               osrfLogWarning( OSRF_LOG_MARK, "Unable to bind to UDP port %d: %s",
+                       port, strerror( errno ) );
                return -1;
        }
 
@@ -183,8 +212,10 @@ int socket_open_tcp_client(socket_manager* mgr, int port, char* dest_addr) {
    // ------------------------------------------------------------------
    // Create the socket
    // ------------------------------------------------------------------
+   errno = 0;
    if( (sock_fd = socket( AF_INET, SOCK_STREAM, 0 )) < 0 ) {
-      osrfLogWarning( OSRF_LOG_MARK,  "tcp_connect(): Cannot create socket" );
+          osrfLogWarning( OSRF_LOG_MARK,  "socket_open_tcp_client(): Cannot create TCP socket: %s",
+                       strerror( errno ) );
       return -1;
    }
 
@@ -196,8 +227,10 @@ int socket_open_tcp_client(socket_manager* mgr, int port, char* dest_addr) {
    // ------------------------------------------------------------------
    // Get the hostname
    // ------------------------------------------------------------------
+   errno = 0;
    if( (hptr = gethostbyname( dest_addr ) ) == NULL ) {
-      osrfLogWarning(  OSRF_LOG_MARK, "tcp_connect(): Unknown Host => %s", dest_addr );
+          osrfLogWarning(  OSRF_LOG_MARK, "socket_open_tcp_client(): Unknown Host => %s: %s",
+                                               dest_addr, strerror( errno ) );
       return -1;
    }
 
@@ -221,17 +254,21 @@ int socket_open_tcp_client(socket_manager* mgr, int port, char* dest_addr) {
    // ------------------------------------------------------------------
    // Bind to a local port
    // ------------------------------------------------------------------
+   errno = 0;
    if( bind( sock_fd, (struct sockaddr *) &localAddr, sizeof( localAddr ) ) < 0 ) {
-      osrfLogWarning(  OSRF_LOG_MARK, "tcp_connect(): Cannot bind to local port" );
+          osrfLogWarning( OSRF_LOG_MARK, "socket_open_tcp_client(): Cannot bind to local port: %s",
+               strerror( errno ) );
       return -1;
    }
 
    // ------------------------------------------------------------------
    // Connect to server
    // ------------------------------------------------------------------
+   errno = 0;
    if( connect( sock_fd, (struct sockaddr*) &remoteAddr, sizeof( struct sockaddr_in ) ) < 0 ) {
-      osrfLogWarning(  OSRF_LOG_MARK, "tcp_connect(): Cannot connect to server %s", dest_addr );
-      return -1;
+          osrfLogWarning( OSRF_LOG_MARK, "socket_open_tcp_client(): Cannot connect to server %s: %s",
+                  dest_addr, strerror(errno) );
+          return -1;
    }
 
        _socket_add_node(mgr, CLIENT_SOCKET, INET, sock_fd, -1 );
@@ -247,8 +284,10 @@ int socket_open_udp_client(
        struct sockaddr_in client_addr, server_addr;
        struct hostent* host;
 
+       errno = 0;
        if( (host = gethostbyname(dest_addr)) == NULL) {
-               osrfLogWarning( OSRF_LOG_MARK, "Unable to resolve host: %s", dest_addr);
+               osrfLogWarning( OSRF_LOG_MARK, "Unable to resolve host: %s: %s",
+                       dest_addr, strerror( errno ) );
                return -1;
        }
 
@@ -257,8 +296,9 @@ int socket_open_udp_client(
                             host->h_addr_list[0], host->h_length);
        server_addr.sin_port = htons(port);
 
+       errno = 0;
        if( (sockfd = socket(AF_INET,SOCK_DGRAM,0)) < 0 ) {
-               osrfLogWarning( OSRF_LOG_MARK, "Unable to create UDP socket");
+               osrfLogWarning( OSRF_LOG_MARK, "socket_open_udp_client(): Unable to create UDP socket: %s", strerror( errno ) );
                return -1;
        }
 
@@ -266,8 +306,9 @@ int socket_open_udp_client(
        client_addr.sin_addr.s_addr = htonl(INADDR_ANY);
        client_addr.sin_port = htons(0);
 
+       errno = 0;
        if( (bind(sockfd, (struct sockaddr *) &client_addr, sizeof(client_addr))) < 0 ) {
-               osrfLogWarning( OSRF_LOG_MARK, "Unable to bind UDP socket");
+               osrfLogWarning( OSRF_LOG_MARK, "Unable to bind UDP socket: %s", strerror( errno ) );
                return -1;
        }
 
@@ -282,8 +323,9 @@ int socket_open_unix_client(socket_manager* mgr, char* sock_path) {
        int sock_fd, len;
    struct sockaddr_un usock;
 
+   errno = 0;
    if( (sock_fd = socket( AF_UNIX, SOCK_STREAM, 0 )) < 0 ) {
-               osrfLogWarning(  OSRF_LOG_MARK, "Cannot create socket" );
+          osrfLogWarning(  OSRF_LOG_MARK, "socket_open_unix_client(): Cannot create UNIX socket: %s", strerror( errno ) );
                return -1;
        }
 
@@ -292,8 +334,10 @@ int socket_open_unix_client(socket_manager* mgr, char* sock_path) {
 
    len = sizeof( usock.sun_family ) + strlen( usock.sun_path );
 
+   errno = 0;
    if( connect( sock_fd, (struct sockaddr *) &usock, len ) < 0 ) {
-      osrfLogWarning(  OSRF_LOG_MARK, "Error connecting to unix socket" );
+          osrfLogWarning(  OSRF_LOG_MARK, "Error connecting to unix socket: %s",
+                       strerror( errno ) );
                return -1;
        }
 
@@ -303,9 +347,8 @@ int socket_open_unix_client(socket_manager* mgr, char* sock_path) {
 }
 
 
-
 /* returns the socket_node with the given sock_fd */
-socket_node* socket_find_node(socket_manager* mgr, int sock_fd) {
+static socket_node* socket_find_node(socket_manager* mgr, int sock_fd) {
        if(mgr == NULL) return NULL;
        socket_node* node = mgr->socket;
        while(node) {
@@ -317,7 +360,7 @@ socket_node* socket_find_node(socket_manager* mgr, int sock_fd) {
 }
 
 /* removes the node with the given sock_fd from the list and frees it */
-void socket_remove_node(socket_manager* mgr, int sock_fd) {
+static void socket_remove_node(socket_manager* mgr, int sock_fd) {
 
        if(mgr == NULL) return;
 
@@ -349,7 +392,6 @@ void socket_remove_node(socket_manager* mgr, int sock_fd) {
 }
 
 
-
 void _socket_print_list(socket_manager* mgr) {
        if(mgr == NULL) return;
        socket_node* node = mgr->socket;
@@ -367,16 +409,18 @@ int socket_send(int sock_fd, const char* data) {
        return _socket_send( sock_fd, data, 0);
 }
 
-
-int _socket_send(int sock_fd, const char* data, int flags) {
+/* utility method */
+static int _socket_send(int sock_fd, const char* data, int flags) {
 
        signal(SIGPIPE, SIG_IGN); /* in case a unix socket was closed */
 
+       errno = 0;
        size_t r = send( sock_fd, data, strlen(data), flags );
-
+       int local_errno = errno;
+       
        if( r == -1 ) {
-               osrfLogWarning( OSRF_LOG_MARK, "tcp_server_send(): Error sending data with return %d", r );
-               osrfLogWarning( OSRF_LOG_MARK, "Last Sys Error: %s", strerror(errno));
+               osrfLogWarning( OSRF_LOG_MARK, "_socket_send(): Error sending data with return %d", r );
+               osrfLogWarning( OSRF_LOG_MARK, "Last Sys Error: %s", strerror(local_errno));
                return -1;
        }
 
@@ -384,9 +428,13 @@ int _socket_send(int sock_fd, const char* data, int flags) {
 }
 
 
-int socket_send_nowait( int sock_fd, const char* data) {
-       return _socket_send( sock_fd, data, MSG_DONTWAIT);
-}
+/* sends the given data to the given socket. 
+ * sets the send flag MSG_DONTWAIT which will allow the 
+ * process to continue even if the socket buffer is full
+ * returns 0 on success, -1 otherwise */
+//int socket_send_nowait( int sock_fd, const char* data) {
+//     return _socket_send( sock_fd, data, MSG_DONTWAIT);
+//}
 
 
 /*
@@ -408,11 +456,13 @@ int socket_send_timeout( int sock_fd, const char* data, int usecs ) {
        tv.tv_sec = secs;
        tv.tv_usec = usecs;
 
+       errno = 0;
        int ret = select( sock_fd + 1, NULL, &write_set, NULL, &tv);
        if( ret > 0 ) return _socket_send( sock_fd, data, 0);
 
        osrfLogError(OSRF_LOG_MARK, "socket_send_timeout(): "
-               "timed out on send for socket %d after %d secs, %d usecs", sock_fd, secs, usecs );
+               "timed out on send for socket %d after %d secs, %d usecs: %s",
+               sock_fd, secs, usecs, strerror( errno ) );
 
        return -1;
 }
@@ -450,6 +500,7 @@ int socket_wait(socket_manager* mgr, int timeout, int sock_fd) {
        struct timeval tv;
        tv.tv_sec = timeout;
        tv.tv_usec = 0;
+       errno = 0;
 
        if( timeout < 0 ) {  
 
@@ -475,7 +526,7 @@ int socket_wait(socket_manager* mgr, int timeout, int sock_fd) {
 int socket_wait_all(socket_manager* mgr, int timeout) {
 
        if(mgr == NULL) {
-               osrfLogWarning( OSRF_LOG_MARK,  "tcp_wait(): null mgr" );
+               osrfLogWarning( OSRF_LOG_MARK,  "socket_wait_all(): null mgr" );
                return -1;
        }
 
@@ -496,21 +547,20 @@ int socket_wait_all(socket_manager* mgr, int timeout) {
        struct timeval tv;
        tv.tv_sec = timeout;
        tv.tv_usec = 0;
+       errno = 0;
 
        if( timeout < 0 ) {  
 
                // If timeout is -1, there is no timeout passed to the call to select
                if( (retval = select( max_fd, &read_set, NULL, NULL, NULL)) == -1 ) {
-                       osrfLogWarning( OSRF_LOG_MARK, "Call to select interrupted (returned -1)");
-                       osrfLogWarning( OSRF_LOG_MARK, "Sys Error: %s", strerror(errno));
+                       osrfLogWarning( OSRF_LOG_MARK, "select() call aborted: %s", strerror(errno));
                        return -1;
                }
 
        } else if( timeout != 0 ) { /* timeout of 0 means don't block */
 
                if( (retval = select( max_fd, &read_set, NULL, NULL, &tv)) == -1 ) {
-                       osrfLogWarning( OSRF_LOG_MARK,  "Call to select interrupted (returned -1)" );
-                       osrfLogWarning( OSRF_LOG_MARK, "Sys Error: %s", strerror(errno));
+                       osrfLogWarning( OSRF_LOG_MARK, "select() call aborted: %s", strerror(errno));
                        return -1;
                }
        }
@@ -519,9 +569,14 @@ int socket_wait_all(socket_manager* mgr, int timeout) {
        return _socket_route_data(mgr, retval, &read_set);
 }
 
-/* determines if we'er receiving a new client or data
+/* iterates over the sockets in the set and handles active sockets.
+       new sockets connecting to server sockets cause the creation
+       of a new socket node.
+       Any new data read is is passed off to the data_received callback
+       as it arrives */
+/* determines if we're receiving a new client or data
        on an existing client */
-int _socket_route_data(
+static int _socket_route_data(
        socket_manager* mgr, int num_active, fd_set* read_set) {
 
        if(!(mgr && read_set)) return -1;
@@ -584,7 +639,8 @@ int _socket_route_data(
 }
 
 
-int _socket_route_data_id( socket_manager* mgr, int sock_id) {
+/* routes data from a single known socket */
+static int _socket_route_data_id( socket_manager* mgr, int sock_id) {
        socket_node* node = socket_find_node(mgr, sock_id);     
        int status = 0;
 
@@ -606,13 +662,15 @@ int _socket_route_data_id( socket_manager* mgr, int sock_id) {
 }
 
 
-int _socket_handle_new_client(socket_manager* mgr, socket_node* node) {
+static int _socket_handle_new_client(socket_manager* mgr, socket_node* node) {
        if(mgr == NULL || node == NULL) return -1;
 
+       errno = 0;
        int new_sock_fd;
        new_sock_fd = accept(node->sock_fd, NULL, NULL);
        if(new_sock_fd < 0) {
-               osrfLogWarning( OSRF_LOG_MARK, "_socket_route_data(): accept() failed");
+               osrfLogWarning( OSRF_LOG_MARK, "_socket_handle_new_client(): accept() failed: %s",
+                       strerror( errno ) );
                return -1;
        }
 
@@ -629,7 +687,7 @@ int _socket_handle_new_client(socket_manager* mgr, socket_node* node) {
 }
 
 
-int _socket_handle_client_data(socket_manager* mgr, socket_node* node) {
+static int _socket_handle_client_data(socket_manager* mgr, socket_node* node) {
        if(mgr == NULL || node == NULL) return -1;
 
        char buf[RBUFSIZE];
@@ -639,7 +697,7 @@ int _socket_handle_client_data(socket_manager* mgr, socket_node* node) {
        memset(buf, 0, RBUFSIZE);
        set_fl(sock_fd, O_NONBLOCK);
 
-       osrfLogInternal( OSRF_LOG_MARK, "%d : Received data at %f\n", getpid(), get_timestamp_millis());
+       osrfLogInternal( OSRF_LOG_MARK, "%ld : Received data at %f\n", (long) getpid(), get_timestamp_millis());
 
        while( (read_bytes = recv(sock_fd, buf, RBUFSIZE-1, 0) ) > 0 ) {
                osrfLogInternal( OSRF_LOG_MARK, "Socket %d Read %d bytes and data: %s", sock_fd, read_bytes, buf);
@@ -648,12 +706,13 @@ int _socket_handle_client_data(socket_manager* mgr, socket_node* node) {
 
                memset(buf, 0, RBUFSIZE);
        }
+    int local_errno = errno; /* capture errno as set by recv() */
 
        if(socket_find_node(mgr, sock_fd)) {  /* someone may have closed this socket */
                clr_fl(sock_fd, O_NONBLOCK); 
                if(read_bytes < 0) { 
-                       if( errno != EAGAIN 
-                               osrfLogWarning( OSRF_LOG_MARK,  " * Error reading socket with errno %d", errno );
+                       if(local_errno != EAGAIN
+                               osrfLogWarning(OSRF_LOG_MARK,  " * Error reading socket with error %s", strerror(local_errno));
                }
 
        } else { return -1; } /* inform the caller that this node has been tampered with */
@@ -681,3 +740,4 @@ void socket_manager_free(socket_manager* mgr) {
        free(mgr);
 
 }
+
index d1f5fd7..28a5405 100644 (file)
@@ -34,9 +34,6 @@
 #define INET 10 
 #define UNIX 11 
 
-/* buffer used to read from the sockets */
-#define RBUFSIZE 1024 
-
 
 /* models a single socket connection */
 struct socket_node_struct {
@@ -87,26 +84,9 @@ int socket_open_unix_client(socket_manager*, char* sock_path);
 
 int socket_open_udp_client( socket_manager* mgr, int port, char* dest_addr);
 
-/* returns the socket_node with the given sock_fd */
-socket_node* socket_find_node(socket_manager*, int sock_fd);
-
-/* removes the node with the given sock_fd from the list and frees it */
-void socket_remove_node(socket_manager*, int sock_fd);
-
-
 /* sends the given data to the given socket. returns 0 on success, -1 otherwise */
 int socket_send(int sock_fd, const char* data);
 
-/* utility method */
-int _socket_send(int sock_fd, const char* data, int flags);
-
-
-/* sends the given data to the given socket. 
- * sets the send flag MSG_DONTWAIT which will allow the 
- * process to continue even if the socket buffer is full
- * returns 0 on success, -1 otherwise */
-int socket_send_nowait( int sock_fd, const char* data);
-
 /* waits at most usecs microseconds for the socket buffer to
  * be available */
 int socket_send_timeout( int sock_fd, const char* data, int usecs );
@@ -115,11 +95,6 @@ int socket_send_timeout( int sock_fd, const char* data, int usecs );
        it from the socket set */
 void socket_disconnect(socket_manager*, int sock_fd);
 
-/* allocates and inserts a new socket node into the nodeset.
-       if parent_id is positive and non-zero, it will be set */
-socket_node*  _socket_add_node(socket_manager* mgr, 
-               int endpoint, int addr_type, int sock_fd, int parent_id );
-
 /* XXX This only works if 'sock_fd' is a client socket... */
 int socket_wait(socket_manager* mgr, int timeout, int sock_fd);
 
@@ -129,24 +104,9 @@ int socket_wait(socket_manager* mgr, int timeout, int sock_fd);
        timeout == x    | block for at most x seconds */
 int socket_wait_all(socket_manager* mgr, int timeout);
 
-/* iterates over the sockets in the set and handles active sockets.
-       new sockets connecting to server sockets cause the creation
-       of a new socket node.
-       Any new data read is is passed off to the data_received callback
-       as it arrives */
-int _socket_route_data(socket_manager* mgr, int num_active, fd_set* read_set);
-
-/* routes data from a single known socket */
-int _socket_route_data_id( socket_manager* mgr, int sock_id);
-
 /* utility function for displaying the currently attached sockets */
 void _socket_print_list(socket_manager* mgr);
 
 int socket_connected(int sock_fd);
 
-
-int _socket_handle_new_client(socket_manager* mgr, socket_node* node);
-int _socket_handle_client_data(socket_manager* mgr, socket_node* node);
-
-
 #endif
index bdeaa96..47b3d2f 100644 (file)
@@ -25,29 +25,37 @@ inline void* safe_malloc( int size ) {
        return ptr;
 }
 
-
-char** __global_argv = NULL;
-int __global_argv_size = 0;
+/****************
+ The following static variables, and the following two functions,
+ overwrite the argv array passed to main().  The purpose is to
+ change the program name as reported by ps and similar utilities.
+
+ Warning: this code makes the non-portable assumption that the
+ strings to which argv[] points are contiguous in memory.  The
+ C Standard makes no such guarantee.
+ ****************/
+static char** global_argv = NULL;
+static int global_argv_size = 0;
 
 int init_proc_title( int argc, char* argv[] ) {
 
-       __global_argv = argv;
+       global_argv = argv;
 
        int i = 0;
        while( i < argc ) {
-               int len = strlen( __global_argv[i]);
-               bzero( __global_argv[i++], len );
-               __global_argv_size += len;
+               int len = strlen( global_argv[i]);
+               bzero( global_argv[i++], len );
+               global_argv_size += len;
        }
 
-       __global_argv_size -= 2;
+       global_argv_size -= 2;
        return 0;
 }
 
 int set_proc_title( char* format, ... ) {
        VA_LIST_TO_STRING(format);
-       bzero( *(__global_argv), __global_argv_size );
-       return snprintf( *(__global_argv), __global_argv_size, VA_BUF );
+       bzero( *(global_argv), global_argv_size );
+       return snprintf( *(global_argv), global_argv_size, VA_BUF );
 }
 
 
@@ -65,17 +73,14 @@ int set_fl( int fd, int flags ) {
        
        int val;
 
-       if( (val = fcntl( fd, F_GETFL, 0) ) < 0 ) {
-               fprintf(stderr, "fcntl F_GETFL error");
+       if( (val = fcntl( fd, F_GETFL, 0) ) < 0 ) 
                return -1;
-       }
 
        val |= flags;
 
-       if( fcntl( fd, F_SETFL, val ) < 0 ) {
-               fprintf(stderr, "fcntl F_SETFL error");
+       if( fcntl( fd, F_SETFL, val ) < 0 ) 
                return -1;
-       }
+
        return 0;
 }
        
@@ -83,17 +88,14 @@ int clr_fl( int fd, int flags ) {
        
        int val;
 
-       if( (val = fcntl( fd, F_GETFL, 0) ) < 0 ) {
-               fprintf(stderr, "fcntl F_GETFL error" );
+       if( (val = fcntl( fd, F_GETFL, 0) ) < 0 ) 
                return -1;
-       }
 
        val &= ~flags;
 
-       if( fcntl( fd, F_SETFL, val ) < 0 ) {
-               fprintf( stderr, "fcntl F_SETFL error" );
+       if( fcntl( fd, F_SETFL, val ) < 0 ) 
                return -1;
-       }
+
        return 0;
 }
 
@@ -214,6 +216,18 @@ int buffer_reset( growing_buffer *gb){
        return 1;
 }
 
+/* Return a pointer to the text within a growing_buffer, */
+/* while destroying the growing_buffer itself.           */
+
+char* buffer_release( growing_buffer* gb) {
+       char* s = gb->buf;
+       s[gb->n_used] = '\0';
+       free( gb );
+       return s;
+}
+
+/* Destroy a growing_buffer and the text it contains */
+
 int buffer_free( growing_buffer* gb ) {
        if( gb == NULL ) 
                return 0;
index 671650f..66acb74 100644 (file)
@@ -34,12 +34,14 @@ GNU General Public License for more details.
 
 
 #define OSRF_MALLOC(ptr, size) \
-       ptr = (void*) malloc( size ); \
-       if( ptr == NULL ) { \
-               perror("OSRF_MALLOC(): Out of Memory" );\
-               exit(99); \
-       } \
-       memset( ptr, 0, size ); 
+       do {\
+               ptr = (void*) malloc( size ); \
+               if( ptr == NULL ) { \
+                       perror("OSRF_MALLOC(): Out of Memory" );\
+                       exit(99); \
+               } \
+               memset( ptr, 0, size );\
+       } while(0)
 
 
 #define OSRF_BUFFER_ADD(gb, data) \
@@ -175,6 +177,7 @@ int buffer_add(growing_buffer* gb, char* c);
 int buffer_fadd(growing_buffer* gb, const char* format, ... );
 int buffer_reset( growing_buffer* gb);
 char* buffer_data( growing_buffer* gb);
+char* buffer_release( growing_buffer* gb );
 int buffer_free( growing_buffer* gb );
 int buffer_add_char(growing_buffer* gb, char c);
 
index a33c36c..ef631e4 100644 (file)
@@ -48,10 +48,16 @@ jsonObject* _xmlToJSON(xmlNodePtr node, jsonObject* obj) {
                }
 
                xmlNodePtr child = node->children;
-               while(child) {
-                       _xmlToJSON(child, new_obj);
-                       child = child->next;
-               }       
+                if (child) { // at least one...
+                       if (child != node->last) { // more than one -- ignore TEXT nodes
+                               while(child) {
+                                       if (child->type != XML_TEXT_NODE) _xmlToJSON(child, new_obj);
+                                       child = child->next;
+                               }
+                       } else {
+                               _xmlToJSON(child, new_obj);
+                       }
+                }
        }       
 
        return obj;