diff --git a/apps/sam/c/doc/todo.txt b/apps/sam/c/doc/todo.txt
index 6dc2bef8f5e48637c64fe2506159d2ed8e2e89b2..f8f1f6f4ce4eafd0e6f271eda5a558d7c64c6865 100644
--- a/apps/sam/c/doc/todo.txt
+++ b/apps/sam/c/doc/todo.txt
@@ -5,5 +5,4 @@ I need to do these things:
 
 Anyone can help with these things:
 
-* Fix the example dgram-client.c
 * Compile on as many platforms as possible
diff --git a/apps/sam/c/doc/whatsnew.txt b/apps/sam/c/doc/whatsnew.txt
index 55b564fc8e957394152b3871ac9824d5ebe9ada8..851e59cb9222e733b59215e2ee82afe256699765 100644
--- a/apps/sam/c/doc/whatsnew.txt
+++ b/apps/sam/c/doc/whatsnew.txt
@@ -1,4 +1,8 @@
+/* vi:set ts=4: */
+
 v1.25
+	* Removed the old broken examples and added more comments to
+		warhammer-dgram.c
 	* Added support for sessions - now LibSAM can have multiple SAM sessions
 		going at once (with different destinations)
 	* Rewrote sendq functions to automatically send big packets, for better
diff --git a/apps/sam/c/examples/i2p-ping/Makefile b/apps/sam/c/examples/i2p-ping/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..96f6a8cafb6e23e71a899ab7f3a7c81fcf95f06c
--- /dev/null
+++ b/apps/sam/c/examples/i2p-ping/Makefile
@@ -0,0 +1,34 @@
+#
+# This Makefile is compatible with GNU Make
+#
+
+#
+# Programs
+#
+
+CC = gcc
+
+#
+# Flags
+#
+
+CFLAGS = -g -O2 -pipe -std=c99 -Wall
+CFLAGS += -I../../inc -L../../lib
+LIBS = -lsam
+
+#
+# Build rules
+#
+
+all: i2p-ping
+
+i2p-ping:
+	$(CC) $(CFLAGS) -o i2p-ping.o -c i2p-ping.c
+	$(CC) $(CFLAGS) -o i2p-ping i2p-ping.o $(LIBS)
+
+#
+# Cleanup rules
+#
+
+clean:
+	-rm -f *.o *.exe i2p-ping
diff --git a/apps/sam/c/examples/i2p-ping/i2p-ping.c b/apps/sam/c/examples/i2p-ping/i2p-ping.c
new file mode 100644
index 0000000000000000000000000000000000000000..1f230c4ae1fadb5121c548a97b2bdd8f0d0d4aae
--- /dev/null
+++ b/apps/sam/c/examples/i2p-ping/i2p-ping.c
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the author nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include "sam.h"
+
+static void usage();
+
+static void closeback(sam_sess_t *session, sam_sid_t stream_id,
+	samerr_t reason);
+static void connectback(sam_sess_t *session, sam_sid_t stream_id,
+	sam_pubkey_t dest);
+static void databack(sam_sess_t *session, sam_sid_t stream_id, void *data,
+	size_t size);
+static void diedback(sam_sess_t *session);
+static void logback(char *s);
+static void namingback(char *name, sam_pubkey_t pubkey, samerr_t result);
+static void statusback(sam_sess_t *session, sam_sid_t stream_id,
+	samerr_t result);
+
+bool gotdest = false;
+sam_pubkey_t dest;
+bool quiet = false;
+samerr_t laststatus = SAM_NULL;
+sam_sid_t laststream = 0;
+
+int main(int argc, char* argv[])
+{
+	int ch;
+	int count = 1;  /* number of times to ping */
+	char *samhost = "localhost";
+	uint16_t samport = 7656;
+
+	while ((ch = getopt(argc, argv, "c:h:p:qv")) != -1) {
+		switch (ch) {
+			case 'c':  /* packet count */
+				count = atoi(optarg);
+				break;
+			case 'h':  /* SAM host */
+				samhost = optarg;
+				break;
+			case 'p':  /* SAM port */
+				samport = atoi(optarg);
+				break;
+			case 'q':  /* quiet mode */
+				quiet = true;
+				break;
+			case 'v':  /* version */
+				puts("$Id$");
+				puts("Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>");
+				return 0;
+			case '?':
+			default:
+				usage();
+				return 0;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+	if (argc == 0 || argc > 1) {  /* they forgot to specify a ping target */
+		fprintf(stderr, "Invalid number of targets\n");
+		usage();
+		return 1;
+	}
+
+	/* Hook up the callback functions - required by LibSAM */
+	sam_closeback = &closeback;
+	sam_connectback = &connectback;
+	sam_databack = &databack;
+	sam_diedback = &diedback;
+	sam_logback = &logback;
+	sam_namingback = &namingback;
+	sam_statusback = &statusback;
+
+	sam_sess_t *session = NULL;  /* set to NULL to have LibSAM do the malloc */
+	session = sam_session_init(session);  /* malloc and set defaults */
+	samerr_t rc = sam_connect(session, samhost, samport, "TRANSIENT",
+		SAM_STREAM, 0);
+	if (rc != SAM_OK) {
+		fprintf(stderr, "SAM connection failed: %s\n", sam_strerror(rc));
+		sam_session_free(&session);
+		return 1;
+	}
+
+	if (strlen(argv[0]) == 516) {
+		memcpy(dest, argv[0], SAM_PUBKEY_LEN);
+		gotdest = true;
+	} else
+		sam_naming_lookup(session, argv[0]);
+
+	while (!gotdest)  /* just wait for the naming lookup to complete */
+		sam_read_buffer(session);
+
+	for (int i = 0; i < count; ++i) {
+		time_t start = time(0);
+		sam_sid_t sid = sam_stream_connect(session, dest);
+		while (laststream != sid && laststatus == SAM_NULL)
+			sam_read_buffer(session);  /* wait for the connect */
+		if (laststatus == SAM_OK)
+			sam_stream_close(session, laststream);
+		time_t finish = time(0);
+		laststream = 0;
+		if (laststatus == SAM_OK) {
+			printf("%s: %.0fs\n", argv[0], difftime(finish, start));
+		} else {
+			printf("Ping failed: %s\n", sam_strerror(laststatus));
+		}
+		laststatus = SAM_NULL;
+	}
+
+	sam_close(session);
+	sam_session_free(&session);
+	return 0;
+}
+
+void usage()
+{
+	puts("Ha!  Help?  You've got to be kidding!");
+}
+
+/*
+ * Connection closed
+ */
+static void closeback(sam_sess_t *session, sam_sid_t stream_id, samerr_t reason)
+{
+	fprintf(stderr, "Connection closed to stream %d: %s\n", stream_id,
+		sam_strerror(reason));
+}
+
+/*
+ * Someone connected to us - how dare they!
+ */
+static void connectback(sam_sess_t *session, sam_sid_t stream_id,
+		sam_pubkey_t dest)
+{
+	sam_stream_close(session, stream_id);
+}
+
+/*
+ * A peer sent us some data - just ignore it
+ */
+static void databack(sam_sess_t *session, sam_sid_t stream_id, void *data,
+		size_t size)
+{
+	free(data);
+}
+
+/*
+ * This is called whenever the SAM connection fails (like if the I2P router is
+ * shut down)
+ */
+static void diedback(sam_sess_t *session)
+{
+	fprintf(stderr, "Lost SAM connection!\n");
+	exit(1);
+}
+
+/*
+ * The logging callback prints any logging messages from LibSAM (typically
+ * errors)
+ */
+static void logback(char *s)
+{
+	if (!quiet)
+		fprintf(stderr, "LibSAM: %s\n", s);
+}
+
+/*
+ * This is really hackish, but we know that we are only doing one lookup, so
+ * what the hell
+ */
+static void namingback(char *name, sam_pubkey_t pubkey, samerr_t result)
+{
+	if (result != SAM_OK) {
+		fprintf(stderr, "Naming lookup failed: %s\n", sam_strerror(result));
+		exit(1);
+	}
+	memcpy(dest, pubkey, SAM_PUBKEY_LEN);
+	gotdest = true;
+}
+
+/*
+ * Our connection attempt returned a result
+ */
+static void statusback(sam_sess_t *session, sam_sid_t stream_id,
+		samerr_t result)
+{
+	laststatus = result;
+	laststream = stream_id;
+}
diff --git a/apps/sam/c/examples/warhammer-dgram.c b/apps/sam/c/examples/warhammer-dgram.c
index 40908f932f0a983fecca3213ff4cd12c85c92a5a..0e29dcd9498cf32142f3ea3079cbf0aaebcdde4c 100644
--- a/apps/sam/c/examples/warhammer-dgram.c
+++ b/apps/sam/c/examples/warhammer-dgram.c
@@ -43,7 +43,7 @@
  * LibSAM callbacks - functions in our code that are called by LibSAM when
  * something happens
  */
-static void dgramback(const sam_sess_t *session, sam_pubkey_t dest, void *data,
+static void dgramback(sam_sess_t *session, sam_pubkey_t dest, void *data,
 	size_t size);
 static void diedback(sam_sess_t *session);
 static void logback(char *s);
@@ -141,7 +141,7 @@ int main(int argc, char* argv[])
  * When we receive some data from another peer, just ignore it.  Denial of
  * service programs don't need input ;)
  */
-static void dgramback(const sam_sess_t *session, sam_pubkey_t dest, void *data,
+static void dgramback(sam_sess_t *session, sam_pubkey_t dest, void *data,
 		size_t size)
 {
 	puts("Received a datagram (ignored)");
@@ -155,6 +155,7 @@ static void dgramback(const sam_sess_t *session, sam_pubkey_t dest, void *data,
 static void diedback(sam_sess_t *session)
 {
 	fprintf(stderr, "Lost SAM connection!\n");
+	/* high quality code would do a sam_session_free() here */
 	exit(1);
 }
 
diff --git a/apps/sam/c/inc/sam.h b/apps/sam/c/inc/sam.h
index a338661e3b23ab23dce64fb6985d0ef3f54af89c..2f9ca885c46b8f4ada82a1b7920a54c9c593289d 100644
--- a/apps/sam/c/inc/sam.h
+++ b/apps/sam/c/inc/sam.h
@@ -90,11 +90,13 @@ typedef struct {
 } sam_sess_t;  /* a SAM session */
 
 typedef enum {  /* see sam_strerror() for detailed descriptions of these */
+	/* no error code - not used by me (you can use it in your program) */
+	SAM_NULL = 0,
 	/* error codes from SAM itself (SAM_OK is not an actual "error") */
 	SAM_OK, SAM_CANT_REACH_PEER, SAM_DUPLICATED_DEST, SAM_I2P_ERROR,
 	SAM_INVALID_KEY, SAM_KEY_NOT_FOUND, SAM_PEER_NOT_FOUND, SAM_TIMEOUT,
 	SAM_UNKNOWN,
-	/* error codes from libsam */
+	/* error codes from LibSAM */
 	SAM_BAD_VERSION, SAM_CALLBACKS_UNSET, SAM_SOCKET_ERROR, SAM_TOO_BIG
 } samerr_t;
 
@@ -127,14 +129,14 @@ extern sam_sid_t sam_stream_connect(sam_sess_t *session,
 extern samerr_t	sam_stream_send(sam_sess_t *session, sam_sid_t stream_id,
 					const void *data, size_t size);
 /* Stream commands - callbacks */
-extern void		(*sam_closeback)(const sam_sess_t *session, sam_sid_t stream_id,
+extern void		(*sam_closeback)(sam_sess_t *session, sam_sid_t stream_id,
 					samerr_t reason);
-extern void		(*sam_connectback)(const sam_sess_t *session,
-					sam_sid_t stream_id, sam_pubkey_t dest);
-extern void		(*sam_databack)(const sam_sess_t *session, sam_sid_t stream_id,
+extern void		(*sam_connectback)(sam_sess_t *session, sam_sid_t stream_id,
+					sam_pubkey_t dest);
+extern void		(*sam_databack)(sam_sess_t *session, sam_sid_t stream_id,
 					void *data, size_t size);
-extern void		(*sam_statusback)(const sam_sess_t *session,
-					sam_sid_t stream_id, samerr_t result);
+extern void		(*sam_statusback)(sam_sess_t *session, sam_sid_t stream_id,
+					samerr_t result);
 
 /* Stream send queue (experimental) */
 extern void		sam_sendq_add(sam_sess_t *session, sam_sid_t stream_id,
@@ -147,7 +149,7 @@ extern samerr_t	sam_dgram_send(sam_sess_t *session, const sam_pubkey_t dest,
 					const void *data, size_t size);
 
 /* Datagram commands - callbacks */
-extern void		(*sam_dgramback)(const sam_sess_t *session, sam_pubkey_t dest,
+extern void		(*sam_dgramback)(sam_sess_t *session, sam_pubkey_t dest,
 					void *data, size_t size);
 
 #ifdef __cplusplus
diff --git a/apps/sam/c/src/sam.c b/apps/sam/c/src/sam.c
index bc32282b62c6674884b509719f242c03e8255cc8..4acb29bf09ebea524d2b1c66d2b559933b76d085 100644
--- a/apps/sam/c/src/sam.c
+++ b/apps/sam/c/src/sam.c
@@ -56,26 +56,25 @@ static ssize_t		sam_write(sam_sess_t *session, const void *buf, size_t n);
  * Note: if you add a new callback be sure to check for non-NULL in sam_connect
  */
 /* a peer closed the connection */
-void (*sam_closeback)(const sam_sess_t *session, sam_sid_t stream_id,
-	samerr_t reason) = NULL;
+void (*sam_closeback)(sam_sess_t *session, sam_sid_t stream_id, samerr_t reason)
+	= NULL;
 /* a peer connected to us */
-void (*sam_connectback)(const sam_sess_t *session, sam_sid_t stream_id,
+void (*sam_connectback)(sam_sess_t *session, sam_sid_t stream_id,
 	sam_pubkey_t dest) = NULL;
 /* a peer sent some stream data (`data' MUST be freed) */
-void (*sam_databack)(const sam_sess_t *session, sam_sid_t stream_id, void *data,
+void (*sam_databack)(sam_sess_t *session, sam_sid_t stream_id, void *data,
 	size_t size) = NULL;
 /* a peer sent some datagram data (`data' MUST be freed) */
-void (*sam_dgramback)(const sam_sess_t *session, sam_pubkey_t dest, void *data,
+void (*sam_dgramback)(sam_sess_t *session, sam_pubkey_t dest, void *data,
 	size_t size) = NULL;
 /* we lost the connection to the SAM host */
 void (*sam_diedback)(sam_sess_t *session) = NULL;
 /* logging callback */
 void (*sam_logback)(char *str) = NULL;
 /* naming lookup reply - `pubkey' will be NULL if `result' isn't SAM_OK */
-void (*sam_namingback)(char *name, sam_pubkey_t pubkey,
-	samerr_t result) = NULL;
+void (*sam_namingback)(char *name, sam_pubkey_t pubkey, samerr_t result) = NULL;
 /* our connection to a peer has completed */
-void (*sam_statusback)(const sam_sess_t *session, sam_sid_t stream_id,
+void (*sam_statusback)(sam_sess_t *session, sam_sid_t stream_id,
 	samerr_t result) = NULL;
 
 /*