aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camel/ChangeLog12
-rw-r--r--camel/camel-tcp-stream-raw.c74
-rw-r--r--camel/camel-tcp-stream-ssl.c36
-rw-r--r--camel/camel-tcp-stream.c58
-rw-r--r--camel/camel-tcp-stream.h49
5 files changed, 227 insertions, 2 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index 3c82004792..53ca70a954 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,3 +1,15 @@
+2001-01-14 Jeffrey Stedfast <fejj@ximian.com>
+
+ * camel-tcp-stream-ssl.c (stream_getsockopt): Implemented.
+ (stream_setsockopt): Implemented.
+
+ * camel-tcp-stream-raw.c (stream_getsockopt): Implemented.
+ (stream_setsockopt): Implemented.
+
+ * camel-tcp-stream.c (camel_tcp_stream_getsockopt): New method.
+ (camel_tcp_stream_setsockopt): Another new method. I think you get
+ the idea of what these are for so I won't explain them.
+
2001-01-14 Jeffrey Stedfast <fejj@helixcode.com>
* camel-tcp-stream-ssl.[c,h]: New CamelTcpStream class that
diff --git a/camel/camel-tcp-stream-raw.c b/camel/camel-tcp-stream-raw.c
index 4a547a2f6f..5c884fd136 100644
--- a/camel/camel-tcp-stream-raw.c
+++ b/camel/camel-tcp-stream-raw.c
@@ -42,6 +42,8 @@ static int stream_close (CamelStream *stream);
static int stream_connect (CamelTcpStream *stream, struct hostent *host, int port);
static int stream_disconnect (CamelTcpStream *stream);
+static int stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data);
+static int stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data);
static void
camel_tcp_stream_raw_class_init (CamelTcpStreamRawClass *camel_tcp_stream_raw_class)
@@ -61,6 +63,8 @@ camel_tcp_stream_raw_class_init (CamelTcpStreamRawClass *camel_tcp_stream_raw_cl
camel_tcp_stream_class->connect = stream_connect;
camel_tcp_stream_class->disconnect = stream_disconnect;
+ camel_tcp_stream_class->getsockopt = stream_getsockopt;
+ camel_tcp_stream_class->setsockopt = stream_setsockopt;
}
static void
@@ -194,3 +198,73 @@ stream_disconnect (CamelTcpStream *stream)
{
return close (((CamelTcpStreamRaw *)stream)->sockfd);
}
+
+
+static int
+get_sockopt_level (const CamelSockOptData *data)
+{
+ switch (data->option) {
+ case CAMEL_SOCKOPT_MAXSEGMENT:
+ case CAMEL_SOCKOPT_NODELAY:
+ return IPPROTO_TCP;
+ default:
+ return SOL_SOCKET;
+ }
+}
+
+static int
+get_sockopt_optname (const CamelSockOptData *data)
+{
+ switch (data->option) {
+ case CAMEL_SOCKOPT_MAXSEGMENT:
+ return TCP_MAXSEG;
+ case CAMEL_SOCKOPT_NODELAY:
+ return TCP_NODELAY;
+ case CAMEL_SOCKOPT_BROADCAST:
+ return SO_BROADCAST;
+ case CAMEL_SOCKOPT_KEEPALIVE:
+ return SO_KEEPALIVE;
+ case CAMEL_SOCKOPT_LINGER:
+ return SO_LINGER;
+ case CAMEL_SOCKOPT_RECVBUFFERSIZE:
+ return SO_RCVBUF;
+ case CAMEL_SOCKOPT_SENDBUFFERSIZE:
+ return SO_SNDBUF;
+ case CAMEL_SOCKOPT_REUSEADDR:
+ return SO_REUSEADDR;
+ case CAMEL_SOCKOPT_IPTYPEOFSERVICE:
+ return SO_TYPE;
+ default:
+ return -1;
+ }
+}
+
+static int
+stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data)
+{
+ int optname, optlen;
+
+ if ((optname = get_sockopt_optname (data)) == -1)
+ return -1;
+
+ return getsockopt (((CamelTcpStreamRaw *)stream)->sockfd,
+ get_sockopt_level (data),
+ optname,
+ (void *) &data->value,
+ &optlen);
+}
+
+static int
+stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data)
+{
+ int optname, optlen;
+
+ if ((optname = get_sockopt_optname (data)) == -1)
+ return -1;
+
+ return setsockopt (((CamelTcpStreamRaw *)stream)->sockfd,
+ get_sockopt_level (data),
+ optname,
+ (void *) &data->value,
+ sizeof (data->value));
+}
diff --git a/camel/camel-tcp-stream-ssl.c b/camel/camel-tcp-stream-ssl.c
index e12d32251d..93b2e9da25 100644
--- a/camel/camel-tcp-stream-ssl.c
+++ b/camel/camel-tcp-stream-ssl.c
@@ -40,8 +40,10 @@ static ssize_t stream_write (CamelStream *stream, const char *buffer, size_t n);
static int stream_flush (CamelStream *stream);
static int stream_close (CamelStream *stream);
-static int stream_connect (CamelTcpStream *stream, struct hostent *host, int port);
+static int stream_connect (CamelTcpStream *stream, struct hostent *host, int port);
static int stream_disconnect (CamelTcpStream *stream);
+static int stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data);
+static int stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data);
static void
camel_tcp_stream_ssl_class_init (CamelTcpStreamSSLClass *camel_tcp_stream_ssl_class)
@@ -61,6 +63,8 @@ camel_tcp_stream_ssl_class_init (CamelTcpStreamSSLClass *camel_tcp_stream_ssl_cl
camel_tcp_stream_class->connect = stream_connect;
camel_tcp_stream_class->disconnect = stream_disconnect;
+ camel_tcp_stream_class->getsockopt = stream_getsockopt;
+ camel_tcp_stream_class->setsockopt = stream_setsockopt;
}
static void
@@ -203,3 +207,33 @@ stream_disconnect (CamelTcpStream *stream)
return PR_Close (((CamelTcpStreamSSL *)stream)->sockfd);
}
+
+static int
+stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data)
+{
+ PRSocketOptionData sodata;
+
+ memset ((void *) &sodata, 0, sizeof (sodata));
+ memcpy ((void *) &sodata, (void *) data, sizeof (CamelSockOptData));
+
+ if (PR_GetSocketOption (((CamelTcpStreamSSL *)stream)->sockfd, &sodata) == PR_FAILURE)
+ return -1;
+
+ memcpy ((void *) data, (void *) &sodata, sizeof (CamelSockOptData));
+
+ return 0;
+}
+
+static int
+stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data)
+{
+ PRSocketOptionData sodata;
+
+ memset ((void *) &sodata, 0, sizeof (sodata));
+ memcpy ((void *) &sodata, (void *) data, sizeof (CamelSockOptData));
+
+ if (PR_SetSocketOption (((CamelTcpStreamRaw *)stream)->sockfd, &sodata) == PR_FAILURE)
+ return -1;
+
+ return 0;
+}
diff --git a/camel/camel-tcp-stream.c b/camel/camel-tcp-stream.c
index e6ac31f450..d335cc7393 100644
--- a/camel/camel-tcp-stream.c
+++ b/camel/camel-tcp-stream.c
@@ -32,6 +32,8 @@ static CamelStreamClass *parent_class = NULL;
static int tcp_connect (CamelTcpStream *stream, struct hostent *host, int port);
static int tcp_disconnect (CamelTcpStream *stream);
+static int tcp_getsockopt (CamelTcpStream *stream, CamelSockOptData *data);
+static int tcp_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data);
static void
camel_tcp_stream_class_init (CamelTcpStreamClass *camel_tcp_stream_class)
@@ -44,6 +46,8 @@ camel_tcp_stream_class_init (CamelTcpStreamClass *camel_tcp_stream_class)
/* tcp stream methods */
camel_tcp_stream_class->connect = tcp_connect;
camel_tcp_stream_class->disconnect = tcp_disconnect;
+ camel_tcp_stream_class->getsockopt = tcp_getsockopt;
+ camel_tcp_stream_class->setsockopt = tcp_setsockopt;
}
static void
@@ -94,7 +98,7 @@ camel_tcp_stream_connect (CamelTcpStream *stream, struct hostent *host, int port
{
g_return_val_if_fail (CAMEL_IS_TCP_STREAM (stream), -1);
- return CTS_CLASS (stream)->connect (stream, offset, policy);
+ return CTS_CLASS (stream)->connect (stream, host, port);
}
@@ -121,3 +125,55 @@ camel_tcp_stream_disconnect (CamelTcpStream *stream)
return CTS_CLASS (stream)->disconnect (stream);
}
+
+
+static int
+tcp_getsockopt (CamelTcpStream *stream, CamelSockOptData *data)
+{
+ g_warning ("CamelTcpStream::getsockopt called on default implementation\n");
+ return -1;
+}
+
+
+/**
+ * camel_tcp_stream_getsockopt:
+ * @stream: tcp stream object
+ * @data: socket option data
+ *
+ * Get the socket options set on the stream and populate #data.
+ *
+ * Return value: zero on success or -1 on fail.
+ **/
+int
+camel_tcp_stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data)
+{
+ g_return_val_if_fail (CAMEL_IS_TCP_STREAM (stream), -1);
+
+ return CTS_CLASS (stream)->getsockopt (stream, data);
+}
+
+
+static int
+tcp_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data)
+{
+ g_warning ("CamelTcpStream::setsockopt called on default implementation\n");
+ return -1;
+}
+
+
+/**
+ * camel_tcp_stream_setsockopt:
+ * @stream: tcp stream object
+ * @data: socket option data
+ *
+ * Set the socket options contained in #data on the stream.
+ *
+ * Return value: zero on success or -1 on fail.
+ **/
+int
+camel_tcp_stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data)
+{
+ g_return_val_if_fail (CAMEL_IS_TCP_STREAM (stream), -1);
+
+ return CTS_CLASS (stream)->setsockopt (stream, data);
+}
diff --git a/camel/camel-tcp-stream.h b/camel/camel-tcp-stream.h
index 35eae89663..63ad6e7ec4 100644
--- a/camel/camel-tcp-stream.h
+++ b/camel/camel-tcp-stream.h
@@ -34,6 +34,7 @@ extern "C" {
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
+#include <netinet/tcp.h>
#include <unistd.h>
#define CAMEL_TCP_STREAM_TYPE (camel_tcp_stream_get_type ())
@@ -41,6 +42,50 @@ extern "C" {
#define CAMEL_TCP_STREAM_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_TCP_STREAM_TYPE, CamelTcpStreamClass))
#define CAMEL_IS_TCP_STREAM(o) (CAMEL_CHECK_TYPE((o), CAMEL_TCP_STREAM_TYPE))
+typedef enum {
+ CAMEL_SOCKOPT_NONBLOCKING, /* nonblocking io */
+ CAMEL_SOCKOPT_LINGER, /* linger on close if data present */
+ CAMEL_SOCKOPT_REUSEADDR, /* allow local address reuse */
+ CAMEL_SOCKOPT_KEEPALIVE, /* keep connections alive */
+ CAMEL_SOCKOPT_RECVBUFFERSIZE, /* receive buffer size */
+ CAMEL_SOCKOPT_SENDBUFFERSIZE, /* send buffer size */
+
+ CAMEL_SOCKOPT_IPTIMETOLIVE, /* time to live */
+ CAMEL_SOCKOPT_IPTYPEOFSERVICE, /* type of service and precedence */
+
+ CAMEL_SOCKOPT_ADDMEMBER, /* add an IP group membership */
+ CAMEL_SOCKOPT_DROPMEMBER, /* drop an IP group membership */
+ CAMEL_SOCKOPT_MCASTINTERFACE, /* multicast interface address */
+ CAMEL_SOCKOPT_MCASTTIMETOLIVE, /* multicast timetolive */
+ CAMEL_SOCKOPT_MCASTLOOPBACK, /* multicast loopback */
+
+ CAMEL_SOCKOPT_NODELAY, /* don't delay send to coalesce packets */
+ CAMEL_SOCKOPT_MAXSEGMENT, /* maximum segment size */
+ CAMEL_SOCKOPT_BROADCAST, /* enable broadcast */
+ CAMEL_SOCKOPT_LAST
+} CamelSockOpt;
+
+typedef struct linger CamelLinger;
+
+typedef struct _CamelSockOptData {
+ CamelSockOpt option;
+ union {
+ guint ip_ttl; /* IP time to live */
+ guint mcast_ttl; /* IP multicast time to live */
+ guint tos; /* IP type of service and precedence */
+ gboolean non_blocking; /* Non-blocking (network) I/O */
+ gboolean reuse_addr; /* Allow local address reuse */
+ gboolean keep_alive; /* Keep connections alive */
+ gboolean mcast_loopback; /* IP multicast loopback */
+ gboolean no_delay; /* Don't delay send to coalesce packets */
+ gboolean broadcast; /* Enable broadcast */
+ size_t max_segment; /* Maximum segment size */
+ size_t recv_buffer_size; /* Receive buffer size */
+ size_t send_buffer_size; /* Send buffer size */
+ CamelLinger linger; /* Time to linger on close if data present */
+ } value;
+} CamelSockOptData;
+
struct _CamelTcpStream
{
CamelStream parent_object;
@@ -53,6 +98,8 @@ typedef struct {
/* Virtual methods */
int (*connect) (CamelTcpStream *stream, struct hostent *host, int port);
int (*disconnect) (CamelTcpStream *stream);
+ int (*getsockopt) (CamelTcpStream *stream, CamelSockOptData *data);
+ int (*setsockopt) (CamelTcpStream *stream, const CamelSockOptData *data);
} CamelTcpStreamClass;
@@ -62,6 +109,8 @@ CamelType camel_tcp_stream_get_type (void);
/* public methods */
int camel_tcp_stream_connect (CamelTcpStream *stream, struct hostent *host, int port);
int camel_tcp_stream_disconnect (CamelTcpStream *stream);
+int camel_tcp_stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data);
+int camel_tcp_stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data);
#ifdef __cplusplus
}