[Opensrf-commits] r1825 - in trunk: include/opensrf src/libopensrf (scottmk)
svn at svn.open-ils.org
svn at svn.open-ils.org
Sun Oct 25 13:02:09 EDT 2009
Author: scottmk
Date: 2009-10-25 13:02:06 -0400 (Sun, 25 Oct 2009)
New Revision: 1825
Modified:
trunk/include/opensrf/socket_bundle.h
trunk/src/libopensrf/socket_bundle.c
Log:
1. Moved several macros from the header to the implementation file. They aren't used
anywhere else.
2. Renamed SERVER_SOCKET and CLIENT_SOCKET to LISTENER_SOCKET and DATA_SOCKET,
respectively. The new names more accurately reflect the uses to which the two
socket types are put. (Note that some so-called CLIENT_SOCKETs were, in fact,
opened by servers.)
3. Changed socket_open_udp_server() to open a DATA_SOCKET (formerly called a
CLIENT_SOCKET) instead of a LISTENER_SOCKET (formerly called a SERVER_SOCKET).
Otherwise an attempt to wait on such a socket would wind up treating it like
a listener. That doesn't work for UDP. In practice this change has no effect,
since no application ever calls this function anyway.
4. Always close a socket before removing the associated socket_node. Otherwise we
will leak sockets in some situations.
5. Tinkered further with the comments, especially in the header file.
M include/opensrf/socket_bundle.h
M src/libopensrf/socket_bundle.c
Modified: trunk/include/opensrf/socket_bundle.h
===================================================================
--- trunk/include/opensrf/socket_bundle.h 2009-10-25 05:35:47 UTC (rev 1824)
+++ trunk/include/opensrf/socket_bundle.h 2009-10-25 17:02:06 UTC (rev 1825)
@@ -1,6 +1,23 @@
#ifndef SOCKET_BUNDLE_H
#define SOCKET_BUNDLE_H
+/**
+ @file socket_bundle.h
+ @brief Header for socket routines.
+
+ These routines cover most of the low-level tedium involved in the use of sockets.
+
+ They support UDP, TCP, and UNIX domain sockets, for both clients and servers. That's six
+ different combinations. They also support the spawning of sockets from a listener
+ by calls to accept(),
+
+ Support for UPD is nominal at best. UDP sockets normally involve the use of calls to
+ recvfrom() or sendto(), but neither of those functions appears here. In practice the
+ functions for opening UDP sockets are completely unused at this writing.
+
+ All socket traffic is expected to consist of text; i.e. binary data is not supported.
+*/
+
#include <opensrf/utils.h>
#include <opensrf/log.h>
@@ -30,76 +47,71 @@
extern "C" {
#endif
-#define SERVER_SOCKET 1
-#define CLIENT_SOCKET 2
-
-#define INET 10
-#define UNIX 11
-
-
/* models a single socket connection */
struct socket_node;
typedef struct socket_node_struct socket_node;
/* Maintains the socket set */
+/**
+ @brief Manages a collection of sockets.
+*/
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);
+ /** @brief Callback for passing any received data up to the calling code.
+ Parameters:
+ - @em blob Opaque pointer from the calling code.
+ - @em mgr Pointer to the socket_manager that manages the socket.
+ - @em sock_fd File descriptor of the socket that read the data.
+ - @em data Pointer to the data received.
+ - @em parent_id (if > 0) listener socket from which the data socket was spawned.
+ */
+ void (*data_received) (
+ void* blob,
+ struct socket_manager_struct* mgr,
+ int sock_fd,
+ char* data,
+ int parent_id
+ );
- void (*on_socket_closed) (void* blob, int sock_fd);
+ /** @brief Callback for closing the socket.
+ Parameters:
+ - @em blob Opaque pointer from the calling code.
+ - @em sock_fd File descriptor of the socket that was closed.
+ */
+ void (*on_socket_closed) (
+ void* blob,
+ int sock_fd
+ );
- socket_node* socket;
- void* blob;
+ socket_node* socket; /**< Linked list of managed sockets. */
+ void* blob; /**< Opaque pointer from the calling code .*/
};
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, const char* listen_ip );
int socket_open_unix_server(socket_manager* mgr, const char* path);
int socket_open_udp_server( socket_manager* mgr, int port, const char* listen_ip );
-/* creates a client TCP socket and adds it to the socket set.
- returns 0 on success. -1 on failure. */
int socket_open_tcp_client(socket_manager*, int port, const char* dest_addr);
-/* creates a client UNIX socket and adds it to the socket set.
- returns 0 on success. -1 on failure. */
int socket_open_unix_client(socket_manager*, const char* sock_path);
int socket_open_udp_client( socket_manager* mgr );
-/* sends the given data to the given socket. returns 0 on success, -1 otherwise */
int socket_send(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 );
-/* disconnects the node with the given sock_fd and removes
- it from the socket set */
void socket_disconnect(socket_manager*, int sock_fd);
-/* XXX This only works if 'sock_fd' is a client socket... */
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);
-/* utility function for displaying the currently attached sockets */
void _socket_print_list(socket_manager* mgr);
int socket_connected(int sock_fd);
Modified: trunk/src/libopensrf/socket_bundle.c
===================================================================
--- trunk/src/libopensrf/socket_bundle.c 2009-10-25 05:35:47 UTC (rev 1824)
+++ trunk/src/libopensrf/socket_bundle.c 2009-10-25 17:02:06 UTC (rev 1825)
@@ -5,19 +5,25 @@
#include <opensrf/socket_bundle.h>
+#define LISTENER_SOCKET 1
+#define DATA_SOCKET 2
+
+#define INET 10
+#define UNIX 11
+
/**
@brief Represents a socket owned by a socket_manager.
A socket_manager owns a linked list of socket_nodes representing the collection of
sockets that it manages. It may contain a single socket for passing data, or it may
- contain a listener socket together with any associated sockets (created by accept())
- for communicating with a client.
+ contain a listener socket (conceivably more than one) together with any associated
+ sockets created by accept() for communicating with a client.
*/
struct socket_node_struct {
- int endpoint; /**< Role of socket: SERVER_SOCKET or CLIENT_SOCKET. */
+ int endpoint; /**< Role of socket: LISTENER_SOCKET or DATA_SOCKET. */
int addr_type; /**< INET or UNIX. */
int sock_fd; /**< File descriptor for socket. */
- int parent_id; /**< If we're a new client for a server socket,
+ int parent_id; /**< For a socket created by accept() for a listener socket,
this is the listener socket we spawned from. */
struct socket_node_struct* next; /**< Linkage pointer for linked list. */
};
@@ -34,12 +40,12 @@
static int _socket_handle_client_data(socket_manager* mgr, socket_node* node);
-/* --------------------------------------------------------------------
- Test Code
+/* --------------------------------------------------------------------
+ Test Code
-------------------------------------------------------------------- */
/*
int count = 0;
-void printme(void* blob, socket_manager* mgr,
+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",
@@ -75,7 +81,7 @@
/**
@brief Create a new socket_node and add it to a socket_manager's list.
@param mgr Pointer to the socket_manager.
- @param endpoint SERVER_SOCKET or CLIENT_SOCKET, denoting how the socket is to be used.
+ @param endpoint LISTENER_SOCKET or DATA_SOCKET, denoting how the socket is to be used.
@param addr_type address type: INET or UNIX.
@param sock_fd sock_fd for the new socket_node.
@param parent_id parent_id for the new node.
@@ -83,7 +89,7 @@
If @a parent_id is negative, the new socket_node receives a parent_id of 0.
*/
-static socket_node* _socket_add_node(socket_manager* mgr,
+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;
@@ -110,12 +116,12 @@
@param listen_ip The IP address to bind to; or, NULL for INADDR_ANY.
@return The socket's file descriptor if successful; otherwise -1.
- Calls: socket(), bind(), and listen(). Creates a SERVER_SOCKET.
+ Calls: socket(), bind(), and listen(). Creates a LISTENER_SOCKET.
*/
int socket_open_tcp_server(socket_manager* mgr, int port, const char* listen_ip) {
if( mgr == NULL ) {
- osrfLogWarning( OSRF_LOG_MARK, "socket_open_tcp_server(): NULL mgr");
+ osrfLogWarning( OSRF_LOG_MARK, "socket_open_tcp_server(): NULL mgr");
return -1;
}
@@ -162,7 +168,7 @@
return -1;
}
- _socket_add_node(mgr, SERVER_SOCKET, INET, sock_fd, 0);
+ _socket_add_node(mgr, LISTENER_SOCKET, INET, sock_fd, 0);
return sock_fd;
}
@@ -172,7 +178,7 @@
@param path Name of the socket within the file system.
@return The socket's file descriptor if successful; otherwise -1.
- Calls: socket(), bind(), listen(). Creates a SERVER_SOCKET.
+ Calls: socket(), bind(), listen(). Creates a LISTENER_SOCKET.
Apply socket option TCP_NODELAY in order to reduce latency.
*/
@@ -202,9 +208,9 @@
strcpy(server_addr.sun_path, path);
errno = 0;
- if( bind(sock_fd, (struct sockaddr*) &server_addr,
+ if( bind(sock_fd, (struct sockaddr*) &server_addr,
sizeof(struct sockaddr_un)) < 0) {
- osrfLogWarning( OSRF_LOG_MARK,
+ osrfLogWarning( OSRF_LOG_MARK,
"socket_open_unix_server(): cannot bind to unix port %s: %s",
path, strerror( errno ) );
close( sock_fd );
@@ -220,17 +226,17 @@
}
osrfLogDebug( OSRF_LOG_MARK, "unix socket successfully opened");
-
+
int i = 1;
/* causing problems with router for some reason ... */
//osrfLogDebug( OSRF_LOG_MARK, "Setting SO_REUSEADDR");
//setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
-
+
//osrfLogDebug( OSRF_LOG_MARK, "Setting TCP_NODELAY");
setsockopt(sock_fd, IPPROTO_TCP, TCP_NODELAY, &i, sizeof(i));
- _socket_add_node(mgr, SERVER_SOCKET, UNIX, sock_fd, 0);
+ _socket_add_node(mgr, LISTENER_SOCKET, UNIX, sock_fd, 0);
return sock_fd;
}
@@ -242,9 +248,9 @@
@param listen_ip The IP address to bind to, or NULL for INADDR_ANY.
@return The socket's file descriptor if successful; otherwise -1.
- Calls: socket(), bind(). Creates a SERVER_SOCKET.
+ Calls: socket(), bind(). Creates a DATA_SOCKET.
*/
-int socket_open_udp_server(
+int socket_open_udp_server(
socket_manager* mgr, int port, const char* listen_ip ) {
int sockfd;
@@ -277,7 +283,7 @@
return -1;
}
- _socket_add_node(mgr, SERVER_SOCKET, INET, sockfd, 0);
+ _socket_add_node(mgr, DATA_SOCKET, INET, sockfd, 0);
return sockfd;
}
@@ -289,7 +295,7 @@
@param dest_addr Host name or IP address of the server to which we are connecting.
@return The socket's file descriptor if successful; otherwise -1.
- Calls: getaddrinfo(), socket(), connect(). Creates a CLIENT_SOCKET.
+ Calls: getaddrinfo(), socket(), connect(). Creates a DATA_SOCKET.
Applies socket option TCP_NODELAY in order to reduce latency.
*/
@@ -321,7 +327,7 @@
if( ! addr_info ) {
osrfLogWarning( OSRF_LOG_MARK,
"socket_open_tcp_client(): Host %s does not support IPV4", dest_addr );
- return -1;
+ return -1;
}
// ------------------------------------------------------------------
@@ -359,7 +365,7 @@
return -1;
}
- _socket_add_node(mgr, CLIENT_SOCKET, INET, sock_fd, -1 );
+ _socket_add_node(mgr, DATA_SOCKET, INET, sock_fd, -1 );
return sock_fd;
}
@@ -370,7 +376,7 @@
@param mgr Pointer to the socket_manager that will own the socket.
@return The socket's file descriptor if successful; otherwise -1.
- Calls: socket(). Creates a CLIENT_SOCKET.
+ Calls: socket(). Creates a DATA_SOCKET.
*/
int socket_open_udp_client( socket_manager* mgr ) {
@@ -383,7 +389,7 @@
return -1;
}
- _socket_add_node(mgr, CLIENT_SOCKET, INET, sockfd, -1 );
+ _socket_add_node(mgr, DATA_SOCKET, INET, sockfd, -1 );
return sockfd;
}
@@ -395,7 +401,7 @@
@param sock_path Name of the socket within the file system.
@return The socket's file descriptor if successful; otherwise -1.
- Calls: socket(), connect(). Creates a CLIENT_SOCKET.
+ Calls: socket(), connect(). Creates a DATA_SOCKET.
*/
int socket_open_unix_client(socket_manager* mgr, const char* sock_path) {
@@ -428,7 +434,7 @@
return -1;
}
- _socket_add_node(mgr, CLIENT_SOCKET, UNIX, sock_fd, -1 );
+ _socket_add_node(mgr, DATA_SOCKET, UNIX, sock_fd, -1 );
return sock_fd;
}
@@ -507,7 +513,7 @@
socket_node* node = mgr->socket;
osrfLogDebug( OSRF_LOG_MARK, "socket_node list: [");
while(node) {
- osrfLogDebug( OSRF_LOG_MARK, "sock_fd: %d | parent_id: %d",
+ osrfLogDebug( OSRF_LOG_MARK, "sock_fd: %d | parent_id: %d",
node->sock_fd, node->parent_id);
node = node->next;
}
@@ -553,8 +559,8 @@
}
-/* sends the given data to the given socket.
- * sets the send flag MSG_DONTWAIT which will allow the
+/* 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) {
@@ -697,12 +703,13 @@
socket_node* node = socket_find_node(mgr, sock_fd);
if( node ) {
- if( node->endpoint == SERVER_SOCKET ) {
+ if( node->endpoint == LISTENER_SOCKET ) {
_socket_handle_new_client( mgr, node ); // accept new connection
} else {
int status = _socket_handle_client_data( mgr, node ); // read data
if( status == -1 ) {
- socket_remove_node(mgr, sock_fd);
+ close( sock_fd );
+ socket_remove_node( mgr, sock_fd );
return -1;
}
}
@@ -730,7 +737,7 @@
socket_manager's list, without actually reading any data.
- Otherwise, read as much data as is available from the input socket, passing it a
buffer at a time to whatever callback function has been defined to the socket_manager.
- */
+*/
int socket_wait_all(socket_manager* mgr, int timeout) {
if(mgr == NULL) {
@@ -757,7 +764,7 @@
tv.tv_usec = 0;
errno = 0;
- if( timeout < 0 ) {
+ if( timeout < 0 ) {
// If timeout is -1, there is no timeout passed to the call to select
if( (num_active = select( max_fd, &read_set, NULL, NULL, NULL)) == -1 ) {
@@ -774,7 +781,7 @@
}
osrfLogDebug( OSRF_LOG_MARK, "%d active sockets after select()", num_active);
-
+
node = mgr->socket;
int handled = 0;
@@ -790,12 +797,13 @@
handled++;
FD_CLR(sock_fd, &read_set);
- if(node->endpoint == SERVER_SOCKET)
+ if(node->endpoint == LISTENER_SOCKET)
_socket_handle_new_client(mgr, node);
else {
if( _socket_handle_client_data(mgr, node) == -1 ) {
/* someone may have yanked a socket_node out from under us */
+ close( sock_fd );
socket_remove_node( mgr, sock_fd );
}
}
@@ -813,7 +821,7 @@
@param node Pointer to the socket_node for the listener socket.
@return 0 if successful, or -1 if not.
- Call: accept(). Creates a CLIENT_SOCKET (even though the socket resides on the server).
+ Call: accept(). Creates a DATA_SOCKET (even though the socket resides on the server).
*/
static int _socket_handle_new_client(socket_manager* mgr, socket_node* node) {
if(mgr == NULL || node == NULL) return -1;
@@ -828,11 +836,11 @@
}
if(node->addr_type == INET) {
- _socket_add_node(mgr, CLIENT_SOCKET, INET, new_sock_fd, node->sock_fd);
+ _socket_add_node(mgr, DATA_SOCKET, INET, new_sock_fd, node->sock_fd);
osrfLogDebug( OSRF_LOG_MARK, "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);
+ _socket_add_node(mgr, DATA_SOCKET, UNIX, new_sock_fd, node->sock_fd);
osrfLogDebug( OSRF_LOG_MARK, "Adding new UNIX client for %d", node->sock_fd);
}
@@ -857,7 +865,7 @@
there may be more data that hasn't arrived yet. It is the responsibility of the
calling code to recognize message boundaries.
- Called only for a CLIENT_SOCKET.
+ Called only for a DATA_SOCKET.
*/
static int _socket_handle_client_data(socket_manager* mgr, socket_node* node) {
if(mgr == NULL || node == NULL) return -1;
More information about the opensrf-commits
mailing list