diff options
-rw-r--r-- | camel/ChangeLog | 12 | ||||
-rw-r--r-- | camel/camel-tcp-stream-raw.c | 74 | ||||
-rw-r--r-- | camel/camel-tcp-stream-ssl.c | 36 | ||||
-rw-r--r-- | camel/camel-tcp-stream.c | 58 | ||||
-rw-r--r-- | camel/camel-tcp-stream.h | 49 |
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 } |