/*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
* See the file LICENSE for details.
*
- * $Id: tcpip.c,v 1.50 2002-09-25 12:37:07 adam Exp $
+ * $Id: tcpip.c,v 1.57 2003-05-13 14:21:13 adam Exp $
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
-#ifndef WIN32
+
+#ifdef WIN32
+#else
#include <unistd.h>
#endif
+
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <yaz/comstack.h>
#include <yaz/tcpip.h>
#include <yaz/log.h>
+#include <yaz/nmem.h>
-/* Chas added the following, so we get the definition of completeBER */
-#include <yaz/odr.h>
+#ifdef WIN32
+#else
+#include <netinet/tcp.h>
+#endif
-int tcpip_close(COMSTACK h);
-int tcpip_put(COMSTACK h, char *buf, int size);
-int tcpip_get(COMSTACK h, char **buf, int *bufsize);
-int tcpip_connect(COMSTACK h, void *address);
-int tcpip_more(COMSTACK h);
-int tcpip_rcvconnect(COMSTACK h);
-int tcpip_bind(COMSTACK h, void *address, int mode);
-int tcpip_listen(COMSTACK h, char *raddr, int *addrlen,
+static int tcpip_close(COMSTACK h);
+static int tcpip_put(COMSTACK h, char *buf, int size);
+static int tcpip_get(COMSTACK h, char **buf, int *bufsize);
+static int tcpip_connect(COMSTACK h, void *address);
+static int tcpip_more(COMSTACK h);
+static int tcpip_rcvconnect(COMSTACK h);
+static int tcpip_bind(COMSTACK h, void *address, int mode);
+static int tcpip_listen(COMSTACK h, char *raddr, int *addrlen,
int (*check_ip)(void *cd, const char *a, int len, int type),
void *cd);
-int static tcpip_set_blocking(COMSTACK p, int blocking);
+static int tcpip_set_blocking(COMSTACK p, int blocking);
#if HAVE_OPENSSL_SSL_H
-int ssl_get(COMSTACK h, char **buf, int *bufsize);
-int ssl_put(COMSTACK h, char *buf, int size);
+static int ssl_get(COMSTACK h, char **buf, int *bufsize);
+static int ssl_put(COMSTACK h, char *buf, int size);
#endif
-COMSTACK tcpip_accept(COMSTACK h);
-char *tcpip_addrstr(COMSTACK h);
-void *tcpip_straddr(COMSTACK h, const char *str);
+static COMSTACK tcpip_accept(COMSTACK h);
+static char *tcpip_addrstr(COMSTACK h);
+static void *tcpip_straddr(COMSTACK h, const char *str);
#if 0
#define TRC(x) x
if (protocol == PROTO_WAIS)
state->complete = completeWAIS;
else
- state->complete = completeBER;
+ state->complete = cs_complete_auto;
p->timeout = COMSTACK_DEFAULT_TIMEOUT;
TRC(fprintf(stderr, "Created new TCPIP comstack\n"));
}
#endif
-int tcpip_strtoaddr_ex(const char *str, struct sockaddr_in *add)
+int tcpip_strtoaddr_ex(const char *str, struct sockaddr_in *add,
+ int default_port)
{
struct hostent *hp;
char *p, buf[512];
- short int port = 210;
+ short int port = default_port;
unsigned tmpadd;
if (!tcpip_init ())
void *tcpip_straddr(COMSTACK h, const char *str)
{
tcpip_state *sp = (tcpip_state *)h->cprivate;
+ int port = 210;
+
+ if (h->protocol == PROTO_HTTP)
+ port = 80;
- if (!tcpip_strtoaddr_ex (str, &sp->addr))
+ if (!tcpip_strtoaddr_ex (str, &sp->addr, port))
return 0;
return &sp->addr;
}
{
static struct sockaddr_in add;
- if (!tcpip_strtoaddr_ex (str, &add))
+ if (!tcpip_strtoaddr_ex (str, &add, 210))
return 0;
return &add;
}
tcpip_state *sp = (tcpip_state *)h->cprivate;
#endif
int r;
-
+#ifdef __sun__
+ int recbuflen;
+ YAZ_SOCKLEN_T rbufsize = sizeof(recbuflen);
+#endif
TRC(fprintf(stderr, "tcpip_connect\n"));
h->io_pending = 0;
if (h->state != CS_ST_UNBND)
h->cerrno = CSOUTSTATE;
return -1;
}
+#ifdef __sun__
+ /* On Suns, you must set a bigger Receive Buffer BEFORE a call to connect
+ * This gives the connect a chance to negotiate with the other side
+ * (see 'man tcp')
+ */
+ if ( getsockopt(h->iofile, SOL_SOCKET, SO_RCVBUF, (void *)&recbuflen, &rbufsize ) < 0 )
+ {
+ h->cerrno = CSYSERR;
+ return -1;
+ }
+ TRC(fprintf( stderr, "Current Size of TCP Receive Buffer= %d\n",
+ recbuflen ));
+ recbuflen *= 10; /* lets be optimistic */
+ if ( setsockopt(h->iofile, SOL_SOCKET, SO_RCVBUF, (void *)&recbuflen, rbufsize ) < 0 )
+ {
+ h->cerrno = CSYSERR;
+ return -1;
+ }
+ if ( getsockopt(h->iofile, SOL_SOCKET, SO_RCVBUF, (void *)&recbuflen, &rbufsize ) )
+ {
+ h->cerrno = CSYSERR;
+ return -1;
+ }
+ TRC(fprintf( stderr, "New Size of TCP Receive Buffer = %d\n",
+ recbuflen ));
+#endif
r = connect(h->iofile, (struct sockaddr *) add, sizeof(*add));
if (r < 0)
{
*/
int tcpip_rcvconnect(COMSTACK h)
{
+#if HAVE_OPENSSL_SSL_H
tcpip_state *sp = (tcpip_state *)h->cprivate;
+#endif
TRC(fprintf(stderr, "tcpip_rcvconnect\n"));
if (h->state == CS_ST_DATAXFER)
#define CERTF "ztest.pem"
#define KEYF "ztest.pem"
-int tcpip_bind(COMSTACK h, void *address, int mode)
+static void tcpip_setsockopt (int fd)
+{
+#if 0
+ int len = 4096;
+ int set = 1;
+
+ if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
+ {
+ yaz_log(LOG_WARN|LOG_ERRNO, "setsockopt TCP_NODELAY");
+ }
+ if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
+ {
+ yaz_log(LOG_WARN|LOG_ERRNO, "setsockopt SNDBUF");
+ }
+ if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
+ {
+ yaz_log(LOG_WARN|LOG_ERRNO, "setsockopt RCVBUF");
+ }
+#endif
+}
+
+static int tcpip_bind(COMSTACK h, void *address, int mode)
{
struct sockaddr *addr = (struct sockaddr *)address;
#ifdef WIN32
return -1;
}
#endif
+ tcpip_setsockopt(h->iofile);
if (bind(h->iofile, addr, sizeof(struct sockaddr_in)))
{
h->cerrno = CSYSERR;
return -1;
}
h->state = CS_ST_INCON;
+ tcpip_setsockopt (h->newfd);
return 0;
}
else if (*bufsize - hasread < CS_TCPIP_BUFCHUNK)
if (!(*buf =(char *)xrealloc(*buf, *bufsize *= 2)))
return -1;
+#ifdef __sun__
+ yaz_set_errno( 0 );
+ // unfortunatly, sun sometimes forgets to set errno in recv
+ // when EWOULDBLOCK etc. would be required (res = -1)
+#endif
res = recv(h->iofile, *buf + hasread, CS_TCPIP_BUFCHUNK, 0);
TRC(fprintf(stderr, " recv res=%d, hasread=%d\n", res, hasread));
if (res < 0)
{
+ TRC(fprintf(stderr, " recv errno=%d, (%s)\n", yaz_errno(),
+ strerror(yaz_errno())));
#ifdef WIN32
if (WSAGetLastError() == WSAEWOULDBLOCK)
{
else if (yaz_errno() == 0)
continue;
else
- return -1;
+ return -1;
#endif
}
else if (!res)
|| yaz_errno() == EAGAIN
#endif
#endif
+#ifdef __sun__
+ || yaz_errno() == ENOENT /* Sun's sometimes set errno to this value! */
+#endif
+ || yaz_errno() == EINPROGRESS
#endif
)
{
r = (char*) host->h_name;
else
r = inet_ntoa(addr.sin_addr);
- sprintf(buf, "tcp:%s", r);
+ if (h->protocol == PROTO_HTTP)
+ sprintf(buf, "http:%s", r);
+ else
+ sprintf(buf, "tcp:%s", r);
#if HAVE_OPENSSL_SSL_H
if (sp->ctx)
- sprintf(buf, "ssl:%s", r);
+ {
+ if (h->protocol == PROTO_HTTP)
+ sprintf(buf, "https:%s", r);
+ else
+ sprintf(buf, "ssl:%s", r);
+ }
#endif
return buf;
}