--- /dev/null
+#include "logging.h"
+
+void get_timestamp( char buf_36chars[]) {
+
+ struct timeb tb;
+ ftime(&tb);
+ char* localtime = strdup( ctime( &(tb.time) ) );
+ char mil[4];
+ memset(mil,0,4);
+ sprintf(mil," (%d)",tb.millitm);
+ strcpy( buf_36chars, localtime );
+ buf_36chars[ strlen(localtime)-1] = '\0'; // remove newline
+ strcat(buf_36chars,mil);
+ free(localtime);
+}
+
+static FILE* log_file = NULL;
+static int log_level = -1;
+static int logging = 0;
+
+void log_free() { if( log_file != NULL ) fclose(log_file ); }
+
+int fatal_handler( char* msg, ... ) {
+
+ char buf[36];
+ memset( buf, 0, 36 );
+ get_timestamp( buf );
+ pid_t pid = getpid();
+ va_list args;
+
+ if( logging ) {
+
+ if( log_level < LOG_ERROR )
+ return -1;
+
+ fprintf( log_file, "[%s %d] [%s] ", buf, pid, "ERR " );
+
+ va_start(args, msg);
+ vfprintf(log_file, msg, args);
+ va_end(args);
+
+ fprintf(log_file, "\n");
+ fflush( log_file );
+
+ }
+
+ /* also log to stderr for ERRORS*/
+ fprintf( stderr, "[%s %d] [%s] ", buf, pid, "ERR " );
+ va_start(args, msg);
+ vfprintf(stderr, msg, args);
+ va_end(args);
+ fprintf( stderr, "\n" );
+
+ exit(99);
+ return -1; /* for consistency */
+}
+
+int warning_handler( char* msg, ... ) {
+
+ char buf[36];
+ memset( buf, 0, 36 );
+ get_timestamp( buf );
+ pid_t pid = getpid();
+ va_list args;
+
+ if(logging) {
+
+ if( log_level < LOG_WARNING )
+ return -1;
+
+ fprintf( log_file, "[%s %d] [%s] ", buf, pid, "WARN" );
+
+ va_start(args, msg);
+ vfprintf(log_file, msg, args);
+ va_end(args);
+
+ fprintf(log_file, "\n");
+ fflush( log_file );
+
+ } else {
+
+ fprintf( stderr, "[%s %d] [%s] ", buf, pid, "WARN" );
+ va_start(args, msg);
+ vfprintf(stderr, msg, args);
+ va_end(args);
+ fprintf( stderr, "\n" );
+ }
+
+ return -1;
+}
+
+int info_handler( char* msg, ... ) {
+
+ char buf[36];
+ memset( buf, 0, 36 );
+ get_timestamp( buf );
+ pid_t pid = getpid();
+ va_list args;
+
+ if(logging) {
+
+ if( log_level < LOG_INFO )
+ return -1;
+ fprintf( log_file, "[%s %d] [%s] ", buf, pid, "INFO" );
+
+ va_start(args, msg);
+ vfprintf(log_file, msg, args);
+ va_end(args);
+
+ fprintf(log_file, "\n");
+ fflush( log_file );
+
+ } else {
+
+ fprintf( stderr, "[%s %d] [%s] ", buf, pid, "INFO" );
+ va_start(args, msg);
+ vfprintf(stderr, msg, args);
+ va_end(args);
+ fprintf( stderr, "\n" );
+ fflush(stderr);
+
+ }
+ return -1;
+}
+
+
+int debug_handler( char* msg, ... ) {
+
+ char buf[36];
+ memset( buf, 0, 36 );
+ get_timestamp( buf );
+ pid_t pid = getpid();
+ va_list args;
+
+ if(logging) {
+
+ if( log_level < LOG_DEBUG )
+ return -1;
+
+ fprintf( log_file, "[%s %d] [%s] ", buf, pid, "DEBG" );
+
+ va_start(args, msg);
+ vfprintf(log_file, msg, args);
+ va_end(args);
+
+ fprintf(log_file, "\n");
+ fflush( log_file );
+
+ } else {
+
+ fprintf( stderr, "[%s %d] [%s] ", buf, pid, "DEBG" );
+ va_start(args, msg);
+ vfprintf(stderr, msg, args);
+ va_end(args);
+ fprintf( stderr, "\n" );
+ }
+
+ return -1;
+}
+
+
+int log_init( int llevel, char* lfile ) {
+
+
+ if( llevel < 1 ) {
+ logging = 0;
+ return 0;
+ }
+
+ log_level = llevel;
+
+ /* log to stderr */
+ if(lfile == NULL) return 0;
+
+ log_file = fopen( lfile, "a" );
+ if( log_file == NULL ) {
+ fprintf( stderr, "Unable to open log file %s for appending\n", lfile );
+ return 0;
+ }
+ logging = 1;
+ return 1;
+
+}
+
+
--- /dev/null
+
+#include <stdarg.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/timeb.h>
+
+#include <string.h>
+#include <time.h>
+#include <stdlib.h>
+
+#ifndef LOGGING_H
+#define LOGGING_H
+
+
+#define LOG_ERROR 1
+#define LOG_WARNING 2
+#define LOG_INFO 3
+#define LOG_DEBUG 4
+
+// ---------------------------------------------------------------------------------
+// Error handling interface.
+// ---------------------------------------------------------------------------------
+void get_timestamp( char buf_36chars[]);
+int fatal_handler( char* message, ...);
+int warning_handler( char* message, ... );
+int info_handler( char* message, ... );
+int debug_handler( char* message, ... );
+
+
+/** If we return 0 either the log level is less than LOG_ERROR
+ * or we could not open the log file
+ */
+int log_init( int log_level, char* log_file );
+void log_free();
+
+#endif
--- /dev/null
+/* --- The MD5 routines --- */
+
+/* MD5 routines, after Ron Rivest */
+/* Written by David Madore <david.madore@ens.fr>, with code taken in
+ * part from Colin Plumb. */
+/* Public domain (1999/11/24) */
+
+/* Note: these routines do not depend on endianness. */
+
+/* === The header === */
+
+/* Put this in md5.h if you don't like having everything in one big
+ * file. */
+
+#ifndef _DMADORE_MD5_H
+#define _DMADORE_MD5_H
+
+struct md5_ctx {
+ /* The four chaining variables */
+ unsigned long buf[4];
+ /* Count number of message bits */
+ unsigned long bits[2];
+ /* Data being fed in */
+ unsigned long in[16];
+ /* Our position within the 512 bits (always between 0 and 63) */
+ int b;
+};
+
+void MD5_transform (unsigned long buf[4], const unsigned long in[16]);
+void MD5_start (struct md5_ctx *context);
+void MD5_feed (struct md5_ctx *context, unsigned char inb);
+void MD5_stop (struct md5_ctx *context, unsigned char digest[16]);
+
+#endif /* not defined _DMADORE_MD5_H */
+
--- /dev/null
+// sha.h
+// Jabber client library
+//
+// Original Code Copyright (C) 1999-2001 Dave Smith (dave@jabber.org)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// Contributor(s): Julian Missig
+//
+// This Original Code has been modified by IBM Corporation. Modifications
+// made by IBM described herein are Copyright (c) International Business
+// Machines Corporation, 2002.
+//
+// Date Modified by Description of modification
+// 01/20/2002 IBM Corp. Updated to libjudo 1.1.1
+// 2002-03-05 IBM Corp. Updated to libjudo 1.1.5
+// 2002-07-09 IBM Corp. Added Roster::getSession()
+//
+// =====================================================================================
+
+
+//#ifdef WIN32
+ char* shahash(const char* str);
+//#else
+//extern "C" {
+// char* shahash(const char* str);
+//}
+//#endif
+
--- /dev/null
+#include "socket_bundle.h"
+
+/* --------------------------------------------------------------------
+ Test Code
+ -------------------------------------------------------------------- */
+/*
+int count = 0;
+void printme(void* blob, socket_manager* mgr,
+ int sock_fd, char* data, int parent_id) {
+
+ fprintf(stderr, "Got data from socket %d with parent %d => %s",
+ sock_fd, parent_id, data );
+
+ socket_send(sock_fd, data);
+
+ if(count++ > 2) {
+ socket_disconnect(mgr, sock_fd);
+ _socket_print_list(mgr);
+ }
+}
+
+int main(int argc, char* argv[]) {
+ socket_manager manager;
+ memset(&manager, 0, sizeof(socket_manager));
+ int port = 11000;
+ if(argv[1])
+ port = atoi(argv[1]);
+
+ manager.data_received = &printme;
+ socket_open_tcp_server(&manager, port);
+
+ while(1)
+ socket_wait_all(&manager, -1);
+
+ return 0;
+}
+*/
+/* -------------------------------------------------------------------- */
+
+
+/*
+int debug_handler(char* msg, ...) {
+ va_list args;
+ va_start(args, msg);
+ vfprintf(stderr, msg, args);
+ va_end(args);
+ fprintf( stderr, "\n" );
+ return -1;
+}
+
+int warning_handler(char* msg, ...) {
+ va_list args;
+ va_start(args, msg);
+ vfprintf(stderr, msg, args);
+ va_end(args);
+ fprintf( stderr, "\n" );
+ return -1;
+}
+*/
+
+
+socket_node* _socket_add_node(socket_manager* mgr,
+ int endpoint, int addr_type, int sock_fd, int parent_id ) {
+
+ if(mgr == NULL) return NULL;
+ debug_handler("Adding socket node with fd %d", sock_fd);
+ socket_node* new_node = safe_malloc(sizeof(socket_node));
+
+ new_node->endpoint = endpoint;
+ new_node->addr_type = addr_type;
+ new_node->sock_fd = sock_fd;
+ new_node->next = NULL;
+ new_node->parent_id = 0;
+ if(parent_id > 0)
+ new_node->parent_id = parent_id;
+
+ new_node->next = mgr->socket;
+ mgr->socket = new_node;
+ return new_node;
+}
+
+/* creates a new server socket node and adds it to the socket set.
+ returns new socket fd on success. -1 on failure.
+ socket_type is one of INET or UNIX */
+int socket_open_tcp_server(socket_manager* mgr, int port) {
+
+ if( mgr == NULL ) return warning_handler("socket_open_tcp_server(): NULL mgr");
+
+ int sock_fd;
+ struct sockaddr_in server_addr;
+
+ sock_fd = socket(AF_INET, SOCK_STREAM, 0);
+
+ if(sock_fd < 0)
+ return warning_handler("tcp_server_connect(): Unable to create socket");
+
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ server_addr.sin_port = htons(port);
+
+ if(bind( sock_fd, (struct sockaddr*) &server_addr, sizeof(server_addr)) < 0)
+ return warning_handler("tcp_server_connect(): cannot bind to port %d", port );
+
+ if(listen(sock_fd, 20) == -1)
+ return warning_handler("tcp_server_connect(): listen() returned error");
+
+ _socket_add_node(mgr, SERVER_SOCKET, INET, sock_fd, 0);
+ return sock_fd;
+}
+
+int socket_open_unix_server(socket_manager* mgr, char* path) {
+ if(mgr == NULL || path == NULL) return -1;
+
+ debug_handler("opening unix socket at %s", path);
+ int sock_fd;
+ struct sockaddr_un server_addr;
+
+ sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if(sock_fd < 0)
+ return warning_handler("socket_open_unix_server(): socket() failed");
+
+ server_addr.sun_family = AF_UNIX;
+ strcpy(server_addr.sun_path, path);
+
+ if( bind(sock_fd, (struct sockaddr*) &server_addr,
+ sizeof(struct sockaddr_un)) < 0) {
+ return warning_handler(
+ "socket_open_unix_server(): cannot bind to unix port %s", path );
+ }
+
+ if(listen(sock_fd, 20) == -1)
+ return warning_handler("socket_open_unix_server(): listen() returned error");
+
+ debug_handler("unix socket successfully opened");
+ _socket_add_node(mgr, SERVER_SOCKET, UNIX, sock_fd, 0);
+ return sock_fd;
+}
+
+
+
+/* creates a client socket and adds it to the socket set.
+ returns 0 on success. -1 on failure.
+ socket_type is one of INET or UNIX */
+int socket_open_client(socket_manager* mgr,
+ int socket_type, int port, char* dest_addr) {
+ return 0;
+}
+
+/* returns the socket_node with the given sock_fd */
+socket_node* socket_find_node(socket_manager* mgr, int sock_fd) {
+ if(mgr == NULL) return NULL;
+ socket_node* node = mgr->socket;
+ while(node) {
+ if(node->sock_fd == sock_fd)
+ return node;
+ node = node->next;
+ }
+ return NULL;
+}
+
+/* removes the node with the given sock_fd from the list and frees it */
+void socket_remove_node(socket_manager* mgr, int sock_fd) {
+
+ if(mgr == NULL) return;
+
+ debug_handler("removing socket %d", sock_fd);
+
+ socket_node* head = mgr->socket;
+ socket_node* tail = head;
+ if(head == NULL) return;
+
+ /* if removing the first node in the list */
+ if(head->sock_fd == sock_fd) {
+ mgr->socket = head->next;
+ free(head);
+ debug_handler("removing first socket in list");
+ return;
+ }
+
+ head = head->next;
+
+ /* if removing any other node */
+ while(head) {
+ if(head->sock_fd == sock_fd) {
+ tail->next = head->next;
+ free(head);
+ return;
+ }
+ tail = head;
+ head = head->next;
+ }
+}
+
+
+
+void _socket_print_list(socket_manager* mgr) {
+ if(mgr == NULL) return;
+ socket_node* node = mgr->socket;
+ debug_handler("socket_node list: [");
+ while(node) {
+ debug_handler("sock_fd: %d | parent_id: %d",
+ node->sock_fd, node->parent_id);
+ node = node->next;
+ }
+ debug_handler("]");
+}
+
+/* sends the given data to the given socket */
+int socket_send(int sock_fd, const char* data) {
+ debug_handler( "socket_bundle sending to %d data %s",
+ sock_fd, data);
+
+ signal(SIGPIPE, SIG_IGN); /* in case a unix socket was closed */
+ if( send( sock_fd, data, strlen(data), 0 ) < 0 ) {
+ return warning_handler( "tcp_server_send(): Error sending data" );
+ }
+
+ return 0;
+}
+
+/* disconnects the node with the given sock_fd and removes
+ it from the socket set */
+void socket_disconnect(socket_manager* mgr, int sock_fd) {
+
+ debug_handler("Closing socket %d", sock_fd);
+ if( close( sock_fd ) == -1 )
+ warning_handler( "socket_disconnect(): Error closing socket, removing anyway" );
+
+ if(mgr != NULL)
+ socket_remove_node(mgr, sock_fd);
+
+}
+
+
+/* we assume that if select() fails, the socket is no longer valid */
+int socket_connected(int sock_fd) {
+ fd_set read_set;
+ FD_ZERO( &read_set );
+ FD_SET( sock_fd, &read_set );
+ if( select( sock_fd + 1, &read_set, NULL, NULL, NULL) == -1 )
+ return 0;
+ return 1;
+
+}
+
+int socket_wait(socket_manager* mgr, int timeout, int sock_fd) {
+ return 0;
+}
+
+
+int socket_wait_all(socket_manager* mgr, int timeout) {
+
+ if(mgr == NULL) return warning_handler( "tcp_wait(): null mgr" );
+
+ int retval = 0;
+ fd_set read_set;
+ FD_ZERO( &read_set );
+
+ socket_node* node = mgr->socket;
+ int max_fd = 0;
+ while(node) {
+ //debug_handler("Adding socket %d to select set",node->sock_fd);
+ FD_SET( node->sock_fd, &read_set );
+ if(node->sock_fd > max_fd) max_fd = node->sock_fd;
+ node = node->next;
+ }
+ max_fd += 1;
+
+ struct timeval tv;
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+
+ if( timeout == -1 ) {
+
+ // 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 ) {
+ return warning_handler("Call to select interrupted");
+ }
+
+ } else if( timeout != 0 ) { /* timeout of 0 means don't block */
+
+ if( (retval = select( max_fd, &read_set, NULL, NULL, &tv)) == -1 ) {
+ return warning_handler( "Call to select interrupted" );
+ }
+ }
+
+ debug_handler("%d active sockets after select()", retval);
+ return _socket_route_data(mgr, retval, &read_set);
+}
+
+/* determines if we'er receiving a new client or data
+ on an existing client */
+int _socket_route_data(
+ socket_manager* mgr, int num_active, fd_set* read_set) {
+
+ socket_node* node = mgr->socket;
+ int handled = 0;
+
+ while(node && (handled < num_active)) {
+
+ int sock_fd = node->sock_fd;
+
+ /* does this socket have data? */
+ if( FD_ISSET( sock_fd, read_set ) ) {
+
+ debug_handler("Socket %d active", sock_fd);
+ handled++;
+ FD_CLR(sock_fd, read_set);
+
+ if(node->endpoint == SERVER_SOCKET)
+ _socket_handle_new_client(mgr, node);
+
+ if(node->endpoint == CLIENT_SOCKET )
+ _socket_handle_client_data(mgr, node);
+
+ } // is_set
+
+ node = node->next;
+
+ } // while(node)
+
+ return 0;
+}
+
+
+int _socket_handle_new_client(socket_manager* mgr, socket_node* node) {
+ if(mgr == NULL || node == NULL) return -1;
+
+ //struct sockaddr_in client_addr_in;
+ //struct sockaddr_un client_addr_un;
+ //int client_len, new_sock_fd;
+
+ int new_sock_fd;
+ new_sock_fd = accept(node->sock_fd, NULL, NULL);
+ if(new_sock_fd < 0)
+ return warning_handler("_socket_route_data(): accept() failed");
+
+ if(node->addr_type == INET) {
+ _socket_add_node(mgr, CLIENT_SOCKET, INET, new_sock_fd, node->sock_fd);
+ debug_handler("Adding new INET client for %d", node->sock_fd);
+
+ } else if(node->addr_type == UNIX) {
+ _socket_add_node(mgr, CLIENT_SOCKET, UNIX, new_sock_fd, node->sock_fd);
+ debug_handler("Adding new UNIX client for %d", node->sock_fd);
+ }
+
+ return 0;
+}
+
+
+int _socket_handle_client_data(socket_manager* mgr, socket_node* node) {
+ if(mgr == NULL || node == NULL) return -1;
+
+ char buf[BUFSIZE];
+ int read_bytes;
+ int sock_fd = node->sock_fd;
+
+ memset(buf, 0, BUFSIZE);
+ set_fl(sock_fd, O_NONBLOCK);
+ debug_handler("Gathering client data for %d", node->sock_fd);
+
+ debug_handler("Socket buf before read %s", buf);
+ while( (read_bytes = recv(sock_fd, buf, BUFSIZE-1, 0) ) > 0 ) {
+ debug_handler("Socket %d Read %d bytes and data: %s", sock_fd, read_bytes, buf);
+
+ /*
+ int l = strlen(buf);
+ if(l > 1) {buf[l-1] = '\0';buf[l-2] = '\0';}
+ debug_handler("Socket data after cleanup: %s", sock_fd, read_bytes, buf);
+ */
+
+
+ if(mgr->data_received)
+ mgr->data_received(mgr->blob, mgr, sock_fd, buf, node->parent_id);
+
+ memset(buf, 0, BUFSIZE);
+ }
+
+ 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 )
+ warning_handler( " * Error reading socket with errno %d", errno );
+ }
+ }
+
+ if(read_bytes == 0) { /* socket closed by client */
+ if(mgr->on_socket_closed)
+ mgr->on_socket_closed(mgr->blob, sock_fd);
+ }
+
+ return 0;
+
+}
+
+
+void socket_manager_free(socket_manager* mgr) {
+ if(mgr == NULL) return;
+ socket_node* tmp;
+ while(mgr->socket) {
+ tmp = mgr->socket->next;
+ socket_disconnect(mgr, mgr->socket->sock_fd);
+ mgr->socket = tmp;
+ }
+ free(mgr);
+
+}
--- /dev/null
+#include "utils.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <errno.h>
+
+#include "utils.h"
+#include "logging.h"
+
+//---------------------------------------------------------------
+// Unix headers
+//---------------------------------------------------------------
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+
+#include <signal.h>
+
+#ifndef SOCKET_BUNDLE_H
+#define SOCKET_BUNDLE_H
+
+
+#define SERVER_SOCKET 1
+#define CLIENT_SOCKET 2
+
+#define INET 10
+#define UNIX 11
+
+/* buffer used to read from the sockets */
+#define BUFSIZE 1024
+
+
+/* models a single socket connection */
+struct socket_node_struct {
+ int endpoint; /* SERVER_SOCKET or CLIENT_SOCKET */
+ int addr_type; /* INET or UNIX */
+ int sock_fd;
+ int parent_id; /* if we're a new client for a server socket,
+ this points to the server socket we spawned from */
+ struct socket_node_struct* next;
+};
+typedef struct socket_node_struct socket_node;
+
+
+/* Maintains the socket set */
+struct socket_manager_struct {
+ /* callback for passing up any received data. sock_fd is the socket
+ that read the data. parent_id (if > 0) is the socket id of the
+ server that this socket spawned from (i.e. it's a new client connection) */
+ void (*data_received)
+ (void* blob, struct socket_manager_struct*,
+ int sock_fd, char* data, int parent_id);
+
+ void (*on_socket_closed) (void* blob, int sock_fd);
+
+ socket_node* socket;
+ void* blob;
+};
+typedef struct socket_manager_struct socket_manager;
+
+void socket_manager_free(socket_manager* mgr);
+
+/* creates a new server socket node and adds it to the socket set.
+ returns socket id on success. -1 on failure.
+ socket_type is one of INET or UNIX */
+int socket_open_tcp_server(socket_manager*, int port);
+
+int socket_open_unix_server(socket_manager* mgr, char* path);
+
+/* creates a client socket and adds it to the socket set.
+ returns 0 on success. -1 on failure.
+ socket_type is one of INET or UNIX */
+int socket_open_client(socket_manager*,
+ int socket_type, 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);
+
+/* disconnects the node with the given sock_fd and removes
+ 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 );
+
+int socket_wait(socket_manager* mgr, int timeout, int sock_fd);
+
+/* waits on all sockets for incoming data.
+ timeout == -1 | block indefinitely
+ timeout == 0 | don't block, just read any available data off all sockets
+ 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);
+
+/* 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
--- /dev/null
+#include "socket_bundle.h"
+
+int count = 0;
+void printme(void* blob, socket_manager* mgr,
+ int sock_fd, char* data, int parent_id) {
+
+ fprintf(stderr, "Got data from socket %d with parent %d => %s",
+ sock_fd, parent_id, data );
+
+ socket_send(sock_fd, data);
+
+ if(count++ > 2) {
+// socket_disconnect(mgr, sock_fd);
+ _socket_print_list(mgr);
+ socket_manager_free(mgr);
+ exit(0);
+ }
+}
+
+int main(int argc, char* argv[]) {
+ socket_manager* manager = safe_malloc(sizeof(socket_manager));
+ int port = 11000;
+ if(argv[1])
+ port = atoi(argv[1]);
+
+ manager->data_received = &printme;
+ socket_open_tcp_server(manager, port);
+
+ while(1)
+ socket_wait_all(manager, -1);
+
+ return 0;
+}
--- /dev/null
+#include "string_array.h"
+
+/*
+int main() {
+ string_array* arr = init_string_array(1);
+ string_array_add(arr, "1");
+ fprintf(stderr,"adding 3\n");
+ string_array_add(arr, "3");
+ string_array_destroy(arr);
+ return 0;
+}
+*/
+
+
+
+string_array* init_string_array(int size) {
+ if(size > STRING_ARRAY_MAX_SIZE)
+ fatal_handler("init_string_array size is too large");
+
+ string_array* arr =
+ (string_array*) safe_malloc(sizeof(string_array));
+ arr->array = (char**) safe_malloc(size * sizeof(char*));
+ arr->size = 0;
+ arr->arr_size = size;
+ return arr;
+}
+
+
+void string_array_add(string_array* arr, char* str) {
+ if(arr == NULL || str == NULL ) {
+ warning_handler("Invalid params to string_array_add");
+ return;
+ }
+
+ if( strlen(str) < 1 ) return;
+
+ arr->size++;
+ //fprintf(stderr,"size is %d\n", arr->size);
+
+ if( arr->size > STRING_ARRAY_MAX_SIZE )
+ fatal_handler("string_array_add size is too large");
+
+ /* if necessary, double capacity */
+ if(arr->size >= arr->arr_size) {
+ arr->arr_size *= 2;
+ debug_handler("string_array: Doubling array size to %d", arr->arr_size);
+ char** tmp = (char**) safe_malloc(arr->arr_size * sizeof(char*));
+ int i;
+
+ /* copy the string pointers over */
+ for( i = 0; i!= arr->size; i++ )
+ tmp[i] = arr->array[i];
+
+ free(arr->array);
+ arr->array = tmp;
+ }
+
+ //fprintf(stderr, "String is %s", str);
+ //debug_handler("string_array_add: Adding string %s", str);
+ //arr->array[arr->size - 1] = (char*) safe_malloc(strlen(str));
+ arr->array[arr->size - 1] = strdup(str);
+ //fprintf(stderr,"we have %s\n", arr->array[arr->size - 1]);
+}
+
+char* string_array_get_string(string_array* arr, int index) {
+ if(!arr || index < 0 || index >= arr->size )
+ return NULL;
+ char* str = arr->array[index];
+
+ if(str == NULL)
+ warning_handler("Somehow we have a NULL string in the string array");
+
+ //debug_handler("string_array_get_string: getting string %s", str);
+ return str;
+}
+
+
+void string_array_destroy(string_array* arr) {
+ if(!arr) return;
+ int i;
+ for( i = 0; i!= arr->size; i++ ) {
+ if( arr->array[i] != NULL ) {
+ //debug_handler("Freeing string from string array %s", arr->array[i]);
+ free(arr->array[i]);
+ }
+ }
+ free(arr->array);
+ free(arr);
+}
--- /dev/null
+#include <stdio.h>
+
+#include "utils.h"
+#include "logging.h"
+
+#define STRING_ARRAY_MAX_SIZE 1024
+
+#ifndef STRING_ARRAY_H
+#define STRING_ARRAY_H
+
+struct string_array_struct {
+ char** array;
+ int size;
+ int arr_size;
+ int total_string_size;
+};
+typedef struct string_array_struct string_array;
+
+string_array* init_string_array(int size);
+void string_array_add(string_array*, char* string);
+
+char* string_array_get_string(string_array* arr, int index);
+void string_array_destroy(string_array*);
+
+/* total size of all included strings */
+int string_array_get_total_size(string_array* arr);
+
+
+#endif
}
+/* setting/clearing file flags */
+int set_fl( int fd, int flags ) {
+
+ int val;
+
+ if( (val = fcntl( fd, F_GETFL, 0) ) < 0 ) {
+ fprintf(stderr, "fcntl F_GETFL error");
+ return -1;
+ }
+
+ val |= flags;
+
+ if( fcntl( fd, F_SETFL, val ) < 0 ) {
+ fprintf(stderr, "fcntl F_SETFL error");
+ return -1;
+ }
+ return 0;
+}
+
+int clr_fl( int fd, int flags ) {
+
+ int val;
+
+ if( (val = fcntl( fd, F_GETFL, 0) ) < 0 ) {
+ fprintf(stderr, "fcntl F_GETFL error" );
+ return -1;
+ }
+
+ val &= ~flags;
+
+ if( fcntl( fd, F_SETFL, val ) < 0 ) {
+ fprintf( stderr, "fcntl F_SETFL error" );
+ return -1;
+ }
+ return 0;
+}
+
// ---------------------------------------------------------------------------------
// Flesh out a ubiqitous growing string buffer
// ---------------------------------------------------------------------------------
--- /dev/null
+#ifndef UTILS_H
+#define UTILS_H
+
+#include <stdarg.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#define BUFFER_MAX_SIZE 10485760
+
+void* safe_malloc(int size);
+
+// ---------------------------------------------------------------------------------
+// Generic growing buffer. Add data all you want
+// ---------------------------------------------------------------------------------
+struct growing_buffer_struct {
+ char *buf;
+ int n_used;
+ int size;
+};
+typedef struct growing_buffer_struct growing_buffer;
+
+growing_buffer* buffer_init( int initial_num_bytes);
+int buffer_addchar(growing_buffer* gb, char c);
+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);
+int buffer_free( growing_buffer* gb );
+int buffer_add_char(growing_buffer* gb, char c);
+
+
+char* uescape( const char* string, int size, int full_escape );
+double get_timestamp_millis();
+
+/* utility methods */
+int set_fl( int fd, int flags );
+int clr_fl( int fd, int flags );
+
+
+
+// Utility method
+double get_timestamp_millis();
+
+
+
+
+#endif