📄 tcpip.c
字号:
*addrlen = 0; if (check_ip && (*check_ip)(cd, (const char *) &addr, sizeof(addr), AF_INET)) { h->cerrno = CSDENY;#ifdef WIN32 closesocket(h->newfd);#else close(h->newfd);#endif h->newfd = -1; return -1; } h->state = CS_ST_INCON; tcpip_setsockopt (h->newfd); return 0;}COMSTACK tcpip_accept(COMSTACK h){ COMSTACK cnew; tcpip_state *state, *st = (tcpip_state *)h->cprivate;#ifdef WIN32 unsigned long tru = 1;#endif TRC(fprintf(stderr, "tcpip_accept\n")); if (h->state == CS_ST_INCON) { if (!(cnew = (COMSTACK)xmalloc(sizeof(*cnew)))) { h->cerrno = CSYSERR;#ifdef WIN32 closesocket(h->newfd);#else close(h->newfd);#endif h->newfd = -1; return 0; } memcpy(cnew, h, sizeof(*h)); cnew->iofile = h->newfd; cnew->io_pending = 0; if (!(state = (tcpip_state *) (cnew->cprivate = xmalloc(sizeof(tcpip_state))))) { h->cerrno = CSYSERR; if (h->newfd != -1) {#ifdef WIN32 closesocket(h->newfd);#else close(h->newfd);#endif h->newfd = -1; } return 0; } if (!cnew->blocking && #ifdef WIN32 (ioctlsocket(cnew->iofile, FIONBIO, &tru) < 0)#else (!cnew->blocking && fcntl(cnew->iofile, F_SETFL, O_NONBLOCK) < 0)#endif ) { h->cerrno = CSYSERR; if (h->newfd != -1) {#ifdef WIN32 closesocket(h->newfd);#else close(h->newfd);#endif h->newfd = -1; } xfree (cnew); xfree (state); return 0; } h->newfd = -1; state->altbuf = 0; state->altsize = state->altlen = 0; state->towrite = state->written = -1; state->complete = st->complete; cnew->state = CS_ST_ACCEPT; h->state = CS_ST_IDLE; #if HAVE_OPENSSL_SSL_H state->ctx = st->ctx; state->ctx_alloc = 0; state->ssl = st->ssl; if (state->ctx) { state->ssl = SSL_new (state->ctx); SSL_set_fd (state->ssl, cnew->iofile); }#endif h = cnew; } if (h->state == CS_ST_ACCEPT) {#if HAVE_OPENSSL_SSL_H tcpip_state *state = (tcpip_state *)h->cprivate; if (state->ctx) { int res = SSL_accept (state->ssl); TRC(fprintf(stderr, "SSL_accept\n")); if (res <= 0) { int err = SSL_get_error(state->ssl, res); if (err == SSL_ERROR_WANT_READ) { h->io_pending = CS_WANT_READ; return h; } if (err == SSL_ERROR_WANT_WRITE) { h->io_pending = CS_WANT_WRITE; return h; } cs_close (h); return 0; } }#endif } else { h->cerrno = CSOUTSTATE; return 0; } h->io_pending = 0; h->state = CS_ST_DATAXFER; h->event = CS_DATA; return h;}#define CS_TCPIP_BUFCHUNK 4096/* * Return: -1 error, >1 good, len of buffer, ==1 incomplete buffer, * 0=connection closed. */int tcpip_get(COMSTACK h, char **buf, int *bufsize){ tcpip_state *sp = (tcpip_state *)h->cprivate; char *tmpc; int tmpi, berlen, rest, req, tomove; int hasread = 0, res; TRC(fprintf(stderr, "tcpip_get: bufsize=%d\n", *bufsize)); if (sp->altlen) /* switch buffers */ { TRC(fprintf(stderr, " %d bytes in altbuf (0x%x)\n", sp->altlen, (unsigned) sp->altbuf)); tmpc = *buf; tmpi = *bufsize; *buf = sp->altbuf; *bufsize = sp->altsize; hasread = sp->altlen; sp->altlen = 0; sp->altbuf = tmpc; sp->altsize = tmpi; } h->io_pending = 0; while (!(berlen = (*sp->complete)((unsigned char *)*buf, hasread))) { if (!*bufsize) { if (!(*buf = (char *)xmalloc(*bufsize = CS_TCPIP_BUFCHUNK))) return -1; } 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) { h->io_pending = CS_WANT_READ; break; } else return -1;#else if (yaz_errno() == EWOULDBLOCK #ifdef EAGAIN #if EAGAIN != EWOULDBLOCK || yaz_errno() == EAGAIN#endif#endif || yaz_errno() == EINPROGRESS#ifdef __sun__ || yaz_errno() == ENOENT /* Sun's sometimes set errno to this */#endif ) { h->io_pending = CS_WANT_READ; break; } else if (yaz_errno() == 0) continue; else return -1;#endif } else if (!res) return 0; hasread += res; } TRC (fprintf (stderr, " Out of read loop with hasread=%d, berlen=%d\n", hasread, berlen)); /* move surplus buffer (or everything if we didn't get a BER rec.) */ if (hasread > berlen) { tomove = req = hasread - berlen; rest = tomove % CS_TCPIP_BUFCHUNK; if (rest) req += CS_TCPIP_BUFCHUNK - rest; if (!sp->altbuf) { if (!(sp->altbuf = (char *)xmalloc(sp->altsize = req))) return -1; } else if (sp->altsize < req) if (!(sp->altbuf =(char *)xrealloc(sp->altbuf, sp->altsize = req))) return -1; TRC(fprintf(stderr, " Moving %d bytes to altbuf(0x%x)\n", tomove, (unsigned) sp->altbuf)); memcpy(sp->altbuf, *buf + berlen, sp->altlen = tomove); } if (berlen < CS_TCPIP_BUFCHUNK - 1) *(*buf + berlen) = '\0'; return berlen ? berlen : 1;}#if HAVE_OPENSSL_SSL_H/* * Return: -1 error, >1 good, len of buffer, ==1 incomplete buffer, * 0=connection closed. */int ssl_get(COMSTACK h, char **buf, int *bufsize){ tcpip_state *sp = (tcpip_state *)h->cprivate; char *tmpc; int tmpi, berlen, rest, req, tomove; int hasread = 0, res; TRC(fprintf(stderr, "ssl_get: bufsize=%d\n", *bufsize)); if (sp->altlen) /* switch buffers */ { TRC(fprintf(stderr, " %d bytes in altbuf (0x%x)\n", sp->altlen, (unsigned) sp->altbuf)); tmpc = *buf; tmpi = *bufsize; *buf = sp->altbuf; *bufsize = sp->altsize; hasread = sp->altlen; sp->altlen = 0; sp->altbuf = tmpc; sp->altsize = tmpi; } h->io_pending = 0; while (!(berlen = (*sp->complete)((unsigned char *)*buf, hasread))) { if (!*bufsize) { if (!(*buf = (char *)xmalloc(*bufsize = CS_TCPIP_BUFCHUNK))) return -1; } else if (*bufsize - hasread < CS_TCPIP_BUFCHUNK) if (!(*buf =(char *)xrealloc(*buf, *bufsize *= 2))) return -1; res = SSL_read (sp->ssl, *buf + hasread, CS_TCPIP_BUFCHUNK); TRC(fprintf(stderr, " SSL_read res=%d, hasread=%d\n", res, hasread)); if (res <= 0) { int ssl_err = SSL_get_error(sp->ssl, res); if (ssl_err == SSL_ERROR_WANT_READ) { h->io_pending = CS_WANT_READ; break; } if (ssl_err == SSL_ERROR_WANT_WRITE) { h->io_pending = CS_WANT_WRITE; break; } if (res == 0) return 0; h->cerrno = CSERRORSSL; return -1; } hasread += res; } TRC (fprintf (stderr, " Out of read loop with hasread=%d, berlen=%d\n", hasread, berlen)); /* move surplus buffer (or everything if we didn't get a BER rec.) */ if (hasread > berlen) { tomove = req = hasread - berlen; rest = tomove % CS_TCPIP_BUFCHUNK; if (rest) req += CS_TCPIP_BUFCHUNK - rest; if (!sp->altbuf) { if (!(sp->altbuf = (char *)xmalloc(sp->altsize = req))) return -1; } else if (sp->altsize < req) if (!(sp->altbuf =(char *)xrealloc(sp->altbuf, sp->altsize = req))) return -1; TRC(fprintf(stderr, " Moving %d bytes to altbuf(0x%x)\n", tomove, (unsigned) sp->altbuf)); memcpy(sp->altbuf, *buf + berlen, sp->altlen = tomove); } if (berlen < CS_TCPIP_BUFCHUNK - 1) *(*buf + berlen) = '\0'; return berlen ? berlen : 1;}#endif/* * Returns 1, 0 or -1 * In nonblocking mode, you must call again with same buffer while * return value is 1. */int tcpip_put(COMSTACK h, char *buf, int size){ int res; struct tcpip_state *state = (struct tcpip_state *)h->cprivate; TRC(fprintf(stderr, "tcpip_put: size=%d\n", size)); h->io_pending = 0; h->event = CS_DATA; if (state->towrite < 0) { state->towrite = size; state->written = 0; } else if (state->towrite != size) { h->cerrno = CSWRONGBUF; return -1; } while (state->towrite > state->written) { 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 yaz_errno() == EWOULDBLOCK #ifdef EAGAIN#if EAGAIN != EWOULDBLOCK || yaz_errno() == EAGAIN#endif#endif#ifdef __sun__ || yaz_errno() == ENOENT /* Sun's sometimes set errno to this value! */#endif || yaz_errno() == EINPROGRESS#endif ) { TRC(fprintf(stderr, " Flow control stop\n")); h->io_pending = CS_WANT_WRITE; return 1; } h->cerrno = CSYSERR; return -1; } state->written += res; TRC(fprintf(stderr, " Wrote %d, written=%d, nbytes=%d\n", res, state->written, size)); } state->towrite = state->written = -1; TRC(fprintf(stderr, " Ok\n")); return 0;}#if HAVE_OPENSSL_SSL_H/* * Returns 1, 0 or -1 * In nonblocking mode, you must call again with same buffer while * return value is 1. */int ssl_put(COMSTACK h, char *buf, int size){ int res; struct tcpip_state *state = (struct tcpip_state *)h->cprivate; TRC(fprintf(stderr, "ssl_put: size=%d\n", size)); h->io_pending = 0; h->event = CS_DATA; if (state->towrite < 0) { state->towrite = size; state->written = 0; } else if (state->towrite != size) { h->cerrno = CSWRONGBUF; return -1; } while (state->towrite > state->written) { res = SSL_write (state->ssl, buf + state->written, size - state->written); if (res <= 0) { int ssl_err = SSL_get_error(state->ssl, res); if (ssl_err == SSL_ERROR_WANT_READ) { h->io_pending = CS_WANT_READ; return 1; } if (ssl_err == SSL_ERROR_WANT_WRITE) { h->io_pending = CS_WANT_WRITE; return 1; } h->cerrno = CSERRORSSL; return -1; } state->written += res; TRC(fprintf(stderr, " Wrote %d, written=%d, nbytes=%d\n", res, state->written, size)); } state->towrite = state->written = -1; TRC(fprintf(stderr, " Ok\n")); return 0;}#endifint tcpip_close(COMSTACK h){ tcpip_state *sp = (struct tcpip_state *)h->cprivate; TRC(fprintf(stderr, "tcpip_close\n")); if (h->iofile != -1) {#if HAVE_OPENSSL_SSL_H if (sp->ssl) { SSL_shutdown (sp->ssl); }#endif#ifdef WIN32 closesocket(h->iofile);#else close(h->iofile);#endif } if (sp->altbuf) xfree(sp->altbuf);#if HAVE_OPENSSL_SSL_H if (sp->ssl) { TRC (fprintf(stderr, "SSL_free\n")); SSL_free (sp->ssl); } sp->ssl = 0; if (sp->ctx_alloc) SSL_CTX_free (sp->ctx_alloc);#endif xfree(sp); xfree(h); return 0;}char *tcpip_addrstr(COMSTACK h){ struct sockaddr_in addr; tcpip_state *sp = (struct tcpip_state *)h->cprivate; char *r, *buf = sp->buf; YAZ_SOCKLEN_T len; struct hostent *host; len = sizeof(addr); if (getpeername(h->iofile, (struct sockaddr*) &addr, &len) < 0) { h->cerrno = CSYSERR; return 0; } if ((host = gethostbyaddr((char*)&addr.sin_addr, sizeof(addr.sin_addr), AF_INET))) r = (char*) host->h_name; else r = inet_ntoa(addr.sin_addr); if (h->protocol == PROTO_HTTP) sprintf(buf, "http:%s", r); else sprintf(buf, "tcp:%s", r);#if HAVE_OPENSSL_SSL_H if (sp->ctx) { if (h->protocol == PROTO_HTTP) sprintf(buf, "https:%s", r); else sprintf(buf, "ssl:%s", r); }#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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -