From eeba94cf59889848a725546dfea7b01f32be24c5 Mon Sep 17 00:00:00 2001 From: erickson Date: Sun, 19 Jun 2005 17:32:45 +0000 Subject: [PATCH] broke out a lot of the code from generic_utils into their own packages and moved them here git-svn-id: svn://svn.open-ils.org/OpenSRF/trunk@359 9efc2488-bf62-4759-914b-345cdb29e865 --- src/utils/logging.c | 185 +++++++++++++++++++++ src/utils/logging.h | 40 +++++ src/utils/md5.h | 35 ++++ src/utils/sha.h | 41 +++++ src/utils/socket_bundle.c | 407 ++++++++++++++++++++++++++++++++++++++++++++++ src/utils/socket_bundle.h | 127 +++++++++++++++ src/utils/socket_test.c | 33 ++++ src/utils/string_array.c | 89 ++++++++++ src/utils/string_array.h | 29 ++++ src/utils/utils.c | 37 +++++ src/utils/utils.h | 50 ++++++ 11 files changed, 1073 insertions(+) create mode 100644 src/utils/logging.c create mode 100644 src/utils/logging.h create mode 100644 src/utils/md5.h create mode 100644 src/utils/sha.h create mode 100644 src/utils/socket_bundle.c create mode 100644 src/utils/socket_bundle.h create mode 100644 src/utils/socket_test.c create mode 100644 src/utils/string_array.c create mode 100644 src/utils/string_array.h create mode 100644 src/utils/utils.h diff --git a/src/utils/logging.c b/src/utils/logging.c new file mode 100644 index 0000000..ebaaf25 --- /dev/null +++ b/src/utils/logging.c @@ -0,0 +1,185 @@ +#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; + +} + + diff --git a/src/utils/logging.h b/src/utils/logging.h new file mode 100644 index 0000000..c2523af --- /dev/null +++ b/src/utils/logging.h @@ -0,0 +1,40 @@ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#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 diff --git a/src/utils/md5.h b/src/utils/md5.h new file mode 100644 index 0000000..53dd2b1 --- /dev/null +++ b/src/utils/md5.h @@ -0,0 +1,35 @@ +/* --- The MD5 routines --- */ + +/* MD5 routines, after Ron Rivest */ +/* Written by David Madore , 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 */ + diff --git a/src/utils/sha.h b/src/utils/sha.h new file mode 100644 index 0000000..6c3d2d4 --- /dev/null +++ b/src/utils/sha.h @@ -0,0 +1,41 @@ +// 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 + diff --git a/src/utils/socket_bundle.c b/src/utils/socket_bundle.c new file mode 100644 index 0000000..113f2f8 --- /dev/null +++ b/src/utils/socket_bundle.c @@ -0,0 +1,407 @@ +#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); + +} diff --git a/src/utils/socket_bundle.h b/src/utils/socket_bundle.h new file mode 100644 index 0000000..3b0121f --- /dev/null +++ b/src/utils/socket_bundle.h @@ -0,0 +1,127 @@ +#include "utils.h" + +#include +#include +#include +#include + +#include "utils.h" +#include "logging.h" + +//--------------------------------------------------------------- +// Unix headers +//--------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#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 diff --git a/src/utils/socket_test.c b/src/utils/socket_test.c new file mode 100644 index 0000000..4bc7653 --- /dev/null +++ b/src/utils/socket_test.c @@ -0,0 +1,33 @@ +#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; +} diff --git a/src/utils/string_array.c b/src/utils/string_array.c new file mode 100644 index 0000000..8290a43 --- /dev/null +++ b/src/utils/string_array.c @@ -0,0 +1,89 @@ +#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); +} diff --git a/src/utils/string_array.h b/src/utils/string_array.h new file mode 100644 index 0000000..0a20eab --- /dev/null +++ b/src/utils/string_array.h @@ -0,0 +1,29 @@ +#include + +#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 diff --git a/src/utils/utils.c b/src/utils/utils.c index 4f92b61..1e2f773 100644 --- a/src/utils/utils.c +++ b/src/utils/utils.c @@ -26,6 +26,43 @@ double get_timestamp_millis() { } +/* 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 // --------------------------------------------------------------------------------- diff --git a/src/utils/utils.h b/src/utils/utils.h new file mode 100644 index 0000000..faa31ca --- /dev/null +++ b/src/utils/utils.h @@ -0,0 +1,50 @@ +#ifndef UTILS_H +#define UTILS_H + +#include +#include +#include +#include +#include +#include + +#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 -- 2.11.0