/*
- * Copyright (c) 1995-2000, Index Data
+ * Copyright (c) 1995-2001, Index Data
* See the file LICENSE for details.
- * Sebastian Hammer, Adam Dickmeiss
*
* $Log: tcpip.c,v $
- * Revision 1.34 2000-11-23 10:58:32 adam
+ * Revision 1.43 2001-10-22 16:00:04 adam
+ * Renamed states for COMSTACKs to avoid confusion with events.
+ *
+ * Revision 1.42 2001/10/22 13:57:24 adam
+ * Implemented cs_rcvconnect and cs_look as described in the documentation.
+ *
+ * Revision 1.41 2001/10/12 21:49:26 adam
+ * For accept/recv/send check for EAGAIN if it's differs from EWOULDBLOCK.
+ *
+ * Revision 1.40 2001/08/23 09:02:46 adam
+ * WIN32 fixes: Socket not re-used for bind. yaz_log logs WIN32 error
+ * message.
+ *
+ * Revision 1.39 2001/07/19 19:49:40 adam
+ * Fixed bug in tcpip_set_blocking.
+ *
+ * Revision 1.38 2001/03/21 12:43:36 adam
+ * Implemented cs_create_host. Better error reporting for SSL comstack.
+ *
+ * Revision 1.37 2001/03/08 20:18:55 adam
+ * Added cs_set_blocking. Patch from Matthew Carey.
+ *
+ * Revision 1.36 2001/02/21 13:46:53 adam
+ * C++ fixes.
+ *
+ * Revision 1.35 2000/11/27 15:17:40 adam
+ * Using SSLeay_add_all_algorithms instead of OpenSSL_add_all_algorithms.
+ *
+ * Revision 1.34 2000/11/23 10:58:32 adam
* SSL comstack support. Separate POSIX thread support library.
*
* Revision 1.33 2000/09/04 08:27:11 adam
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);
#if HAVE_OPENSSL_SSL_H
int ssl_get(COMSTACK h, char **buf, int *bufsize);
p->f_accept = tcpip_accept;
p->f_addrstr = tcpip_addrstr;
p->f_straddr = tcpip_straddr;
+ p->f_set_blocking = tcpip_set_blocking;
- p->state = new_socket ? CS_UNBND : CS_IDLE; /* state of line */
+ p->state = new_socket ? CS_ST_UNBND : CS_ST_IDLE; /* state of line */
p->event = CS_NONE;
p->cerrno = 0;
p->stackerr = 0;
else
{
SSL_load_error_strings();
- OpenSSL_add_all_algorithms();
+ SSLeay_add_all_algorithms();
state->ctx = state->ctx_alloc = SSL_CTX_new (SSLv23_method());
if (!state->ctx)
TRC(fprintf(stderr, "tcpip_connect\n"));
h->io_pending = 0;
- if (h->state == CS_UNBND)
+ if (h->state == CS_ST_UNBND)
{
r = connect(h->iofile, (struct sockaddr *) add, sizeof(*add));
if (r < 0)
#ifdef WIN32
if (WSAGetLastError() == WSAEWOULDBLOCK)
{
- h->state = CS_CONNECTING;
+ h->event = CS_CONNECT;
+ h->state = CS_ST_CONNECTING;
h->io_pending = CS_WANT_WRITE;
return 1;
}
#else
if (errno == EINPROGRESS)
{
- h->state = CS_CONNECTING;
+ h->event = CS_CONNECT;
+ h->state = CS_ST_CONNECTING;
h->io_pending = CS_WANT_WRITE|CS_WANT_READ;
return 1;
}
#endif
+ h->cerrno = CSYSERR;
return -1;
}
- h->state = CS_CONNECTING;
+ h->event = CS_CONNECT;
+ h->state = CS_ST_CONNECTING;
}
- if (h->state != CS_CONNECTING)
+ if (h->state != CS_ST_CONNECTING)
{
h->cerrno = CSOUTSTATE;
return -1;
h->io_pending = CS_WANT_WRITE;
return 1;
}
+ h->cerrno = CSERRORSSL;
return -1;
}
}
#endif
- h->state = CS_DATAXFER;
+ h->event = CS_DATA;
+ h->state = CS_ST_DATAXFER;
return 0;
}
/*
* nop
*/
-int tcpip_rcvconnect(COMSTACK h)
+int tcpip_rcvconnect(COMSTACK cs)
{
TRC(fprintf(stderr, "tcpip_rcvconnect\n"));
- return 0;
+
+ if (cs->event == CS_CONNECT)
+ {
+ int fd = cs->iofile;
+ fd_set input, output;
+ struct timeval tv;
+ int r;
+
+ tv.tv_sec = 0;
+ tv.tv_usec = 1;
+
+ FD_ZERO(&input);
+ FD_ZERO(&output);
+ FD_SET (fd, &input);
+ FD_SET (fd, &output);
+
+ r = select (fd+1, &input, &output, 0, &tv);
+ if (r > 0)
+ {
+ if (FD_ISSET(cs->iofile, &output))
+ {
+ cs->event = CS_DATA;
+ return 0; /* write OK, we're OK */
+ }
+ else
+ return -1; /* an error, for sure */
+ }
+ else if (r == 0)
+ return 0; /* timeout - incomplete */
+ }
+ return -1; /* wrong state or bad select */
}
#define CERTF "ztest.pem"
#else
TRC (fprintf (stderr, "tcpip_bind\n"));
#endif
+#ifndef WIN32
if (setsockopt(h->iofile, SOL_SOCKET, SO_REUSEADDR, (char*)
&one, sizeof(one)) < 0)
{
h->cerrno = CSYSERR;
return -1;
}
- if (bind(h->iofile, addr, sizeof(struct sockaddr_in)) < 0)
+#endif
+ if (bind(h->iofile, addr, sizeof(struct sockaddr_in)))
{
h->cerrno = CSYSERR;
return -1;
h->cerrno = CSYSERR;
return -1;
}
- h->state = CS_IDLE;
+ h->state = CS_ST_IDLE;
+ h->event = CS_LISTEN;
return 0;
}
void *cd)
{
struct sockaddr_in addr;
+#ifdef __cplusplus
+ socklen_t len = sizeof(addr);
+#else
int len = sizeof(addr);
+#endif
TRC(fprintf(stderr, "tcpip_listen pid=%d\n", getpid()));
- if (h->state != CS_IDLE)
+ if (h->state != CS_ST_IDLE)
{
h->cerrno = CSOUTSTATE;
return -1;
#ifdef WIN32
WSAGetLastError() == WSAEWOULDBLOCK
#else
- errno == EWOULDBLOCK
+ errno == EWOULDBLOCK
+#ifdef EAGAIN
+#if EAGAIN != EWOULDBLOCK
+ || errno == EAGAIN
+#endif
+#endif
#endif
)
h->cerrno = CSNODATA;
h->newfd = -1;
return -1;
}
- h->state = CS_INCON;
+ h->state = CS_ST_INCON;
return 0;
}
#endif
TRC(fprintf(stderr, "tcpip_accept\n"));
- if (h->state == CS_INCON)
+ if (h->state == CS_ST_INCON)
{
if (!(cnew = (COMSTACK)xmalloc(sizeof(*cnew))))
{
state->altsize = state->altlen = 0;
state->towrite = state->written = -1;
state->complete = st->complete;
- cnew->state = CS_ACCEPT;
- h->state = CS_IDLE;
+ cnew->state = CS_ST_ACCEPT;
+ h->state = CS_ST_IDLE;
#if HAVE_OPENSSL_SSL_H
state->ctx = st->ctx;
#endif
h = cnew;
}
- if (h->state == CS_ACCEPT)
+ if (h->state == CS_ST_ACCEPT)
{
#if HAVE_OPENSSL_SSL_H
tcpip_state *state = (tcpip_state *)h->cprivate;
return 0;
}
h->io_pending = 0;
- h->state = CS_DATAXFER;
+ h->state = CS_ST_DATAXFER;
+ h->event = CS_DATA;
return h;
}
else
return -1;
#else
- if (errno == EWOULDBLOCK
-#ifdef EINPROGRESS
- || errno == EINPROGRESS
+ if (errno == EWOULDBLOCK
+#ifdef EAGAIN
+#if EAGAIN != EWOULDBLOCK
+ || errno == EAGAIN
#endif
+#endif
+ || errno == EINPROGRESS
)
{
h->io_pending = CS_WANT_READ;
}
if (res == 0)
return 0;
+ h->cerrno = CSERRORSSL;
return -1;
}
hasread += res;
TRC(fprintf(stderr, "tcpip_put: size=%d\n", size));
h->io_pending = 0;
+ h->event = CS_DATA;
if (state->towrite < 0)
{
state->towrite = size;
}
while (state->towrite > state->written)
{
- if ((res = send(h->iofile, buf + state->written, size -
- state->written, 0)) < 0)
+ if ((res =
+ send(h->iofile, buf + state->written, size -
+ state->written,
+#ifdef MSG_NOSIGNAL
+ MSG_NOSIGNAL
+#else
+ 0
+#endif
+ )) < 0)
{
if (
#ifdef WIN32
WSAGetLastError() == WSAEWOULDBLOCK
#else
- errno == EAGAIN
+ errno == EWOULDBLOCK
+#ifdef EAGAIN
+#if EAGAIN != EWOULDBLOCK
+ || errno == EAGAIN
+#endif
+#endif
#endif
)
{
TRC(fprintf(stderr, "ssl_put: size=%d\n", size));
h->io_pending = 0;
+ h->event = CS_DATA;
if (state->towrite < 0)
{
state->towrite = size;
yaz_log (LOG_LOG, "SSL_write. want_write");
return 1;
}
+ h->cerrno = CSERRORSSL;
return -1;
}
state->written += res;
#endif
return buf;
}
+
+int static tcpip_set_blocking(COMSTACK p, int blocking)
+{
+ unsigned long flag;
+
+ if (p->blocking == blocking)
+ return 1;
+#ifdef WIN32
+ flag = 1;
+ if (ioctlsocket(p->iofile, FIONBIO, &flag) < 0)
+ return 0;
+#else
+ flag = fcntl(p->iofile, F_GETFL, 0);
+ if(!blocking)
+ flag = flag & ~O_NONBLOCK;
+ else
+ flag = flag | O_NONBLOCK;
+ if (fcntl(p->iofile, F_SETFL, flag) < 0)
+ return 0;
+#endif
+ p->blocking = blocking;
+ return 1;
+}