Annotation of libwww/Library/src/HTTCP.c, revision 2.84
2.31 frystyk 1: /* HTTCP.c
2.83 frystyk 2: ** TCP SPECIFIC CODE
2.31 frystyk 3: **
2.42 frystyk 4: ** (c) COPYRIGHT MIT 1995.
2.31 frystyk 5: ** Please first read the full copyright statement in the file COPYRIGH.
2.84 ! frystyk 6: ** @(#) $Id: HTTCP.c,v 2.83 1996/04/12 17:49:00 frystyk Exp $
1.1 timbl 7: **
8: ** This code is in common between client and server sides.
9: **
10: ** 16 Jan 92 TBL Fix strtol() undefined on CMU Mach.
11: ** 25 Jun 92 JFG Added DECNET option through TCP socket emulation.
2.7 duns 12: ** 13 Sep 93 MD Added correct return of vmserrorno for HTInetStatus.
13: ** Added decoding of vms error message for MULTINET.
2.13 frystyk 14: ** 31 May 94 HF Added cache on host id's; now use inet_ntoa() to
15: ** HTInetString and some other fixes. Added HTDoConnect
16: ** and HTDoAccept
1.1 timbl 17: */
18:
2.36 frystyk 19: /* Library include files */
2.79 frystyk 20: #include "sysdep.h"
2.83 frystyk 21: #include "WWWUtil.h"
22: #include "WWWCore.h"
23:
2.58 frystyk 24: #include "HTReqMan.h"
2.54 frystyk 25: #include "HTNetMan.h"
2.36 frystyk 26: #include "HTTCP.h" /* Implemented here */
2.29 frystyk 27:
2.36 frystyk 28: /* VMS stuff */
29: #ifdef VMS
30: #ifndef MULTINET
31: #define FD_SETSIZE 32
32: #else /* Multinet */
33: #define FD_SETSIZE 256
34: #endif /* Multinet */
35: #endif /* VMS */
36:
2.13 frystyk 37: /* Macros and other defines */
2.24 frystyk 38: /* x seconds penalty on a multi-homed host if IP-address is down */
39: #define TCP_PENALTY 1200
40:
41: /* x seconds penalty on a multi-homed host if IP-address is timed out */
42: #define TCP_DELAY 600
43:
2.13 frystyk 44: /* ------------------------------------------------------------------------- */
2.19 frystyk 45: /* CONNECTION ESTABLISHMENT MANAGEMENT */
46: /* ------------------------------------------------------------------------- */
2.13 frystyk 47:
48: /* HTDoConnect()
49: **
50: ** Note: Any port indication in URL, e.g., as `host:port' overwrites
2.54 frystyk 51: ** the default port value.
2.13 frystyk 52: **
2.40 frystyk 53: ** returns HT_ERROR Error has occured or interrupted
54: ** HT_OK if connected
55: ** HT_WOULD_BLOCK if operation would have blocked
2.13 frystyk 56: */
2.54 frystyk 57: PUBLIC int HTDoConnect (HTNet * net, char * url, u_short default_port)
2.13 frystyk 58: {
59: int status;
2.65 frystyk 60: HTRequest * request = net->request;
2.55 frystyk 61: char *fullhost = HTParse(url, "", PARSE_HOST);
2.13 frystyk 62: char *at_sign;
63: char *host;
64:
2.54 frystyk 65: /* if there's an @ then use the stuff after it as a hostname */
2.55 frystyk 66: if ((at_sign = strchr(fullhost, '@')) != NULL)
2.13 frystyk 67: host = at_sign+1;
68: else
2.55 frystyk 69: host = fullhost;
2.24 frystyk 70: if (!*host) {
2.65 frystyk 71: HTRequest_addError(request, ERR_FATAL, NO, HTERR_NO_HOST,
2.24 frystyk 72: NULL, 0, "HTDoConnect");
2.76 frystyk 73: HT_FREE(fullhost);
2.40 frystyk 74: return HT_ERROR;
2.27 frystyk 75: }
2.13 frystyk 76:
2.55 frystyk 77: /* Jump into the state machine */
78: while (1) {
79: switch (net->tcpstate) {
80: case TCP_BEGIN:
2.83 frystyk 81: if (PROT_TRACE) HTTrace("HTDoConnect. Looking up `%s\'\n", host);
2.55 frystyk 82: {
83: char *port = strchr(host, ':');
84: SockA *sin = &net->sock_addr;
85: memset((void *) sin, '\0', sizeof(SockA));
2.84 ! frystyk 86: if (port) {
! 87: *port++ = '\0';
! 88: if (*port && isdigit(*port)) {
2.54 frystyk 89: #ifdef DECNET
2.84 ! frystyk 90: sin->sdn_family = AF_DECnet;
! 91: sin->sdn_objnum=(unsigned char)(strtol(port,(char**)0,10));
2.55 frystyk 92: #else
2.84 ! frystyk 93: sin->sin_family = AF_INET;
! 94: sin->sin_port = htons(atol(port));
2.54 frystyk 95: #endif
2.84 ! frystyk 96: }
2.55 frystyk 97: } else {
2.13 frystyk 98: #ifdef DECNET
2.55 frystyk 99: sin->sdn_family = AF_DECnet;
100: net->sock_addr.sdn_objnum = DNP_OBJ;
2.13 frystyk 101: #else /* Internet */
2.55 frystyk 102: sin->sin_family = AF_INET;
103: sin->sin_port = htons(default_port);
2.13 frystyk 104: #endif
2.55 frystyk 105: }
106: }
2.83 frystyk 107:
108: /* Find information about this host */
109: if ((net->host = HTHost_new(host)) == NULL) {
110: if (PROT_TRACE) HTTrace("HTDoConnect. Can't get host info\n");
111: net->tcpstate = TCP_ERROR;
112: break;
113: }
114:
115: /*
116: ** Check whether we have a cached channel for this host. If not
117: ** then go ahead and create a new socket and a new channel. If we
118: ** have to wait for a persistent connection the return. When we
119: ** get back, we check that the socket hasn't been closed in the
120: ** meantime
121: */
122: if ((net->channel = HTHost_channel(net->host)) != NULL) {
123: net->sockfd = HTChannel_socket(net->channel);
124: if (HTChannel_idle(net->channel)) {
125: net->tcpstate = TCP_CONNECTED;
126: break;
127: } else {
128: if (PROT_TRACE) HTTrace("HTDoConnect. Waiting...\n");
129: net->tcpstate = TCP_NEED_CONNECT;
130: HT_FREE(fullhost);
131: HTNet_wait(net);
132: return HT_PERSISTENT;
133: }
134: }
2.55 frystyk 135: net->tcpstate = TCP_DNS;
136: break;
137:
138: case TCP_DNS:
139: if ((status = HTParseInet(net, host)) < 0) {
2.27 frystyk 140: if (PROT_TRACE)
2.77 eric 141: HTTrace("HTDoConnect. Can't locate `%s\'\n", host);
2.65 frystyk 142: HTRequest_addError(request, ERR_FATAL, NO,HTERR_NO_REMOTE_HOST,
2.27 frystyk 143: (void *) host, strlen(host), "HTDoConnect");
2.55 frystyk 144: net->tcpstate = TCP_ERROR;
2.27 frystyk 145: break;
2.55 frystyk 146: }
147: if (!net->retry && status > 1) /* If multiple homes */
148: net->retry = status;
2.83 frystyk 149: net->tcpstate = TCP_NEED_SOCKET;
2.55 frystyk 150: break;
151:
152: case TCP_NEED_SOCKET:
2.27 frystyk 153: #ifdef DECNET
2.36 frystyk 154: if ((net->sockfd=socket(AF_DECnet, SOCK_STREAM, 0))==INVSOC)
2.27 frystyk 155: #else
2.55 frystyk 156: if ((net->sockfd=socket(AF_INET, SOCK_STREAM,IPPROTO_TCP))==INVSOC)
2.27 frystyk 157: #endif
158: {
2.65 frystyk 159: HTRequest_addSystemError(request, ERR_FATAL, socerrno, NO, "socket");
2.55 frystyk 160: net->tcpstate = TCP_ERROR;
2.27 frystyk 161: break;
162: }
163: if (PROT_TRACE)
2.77 eric 164: HTTrace("HTDoConnect. Created socket %d\n",net->sockfd);
2.27 frystyk 165:
2.28 frystyk 166: /* If non-blocking protocol then change socket status
2.82 frystyk 167: ** I use fcntl() so that I can ask the status before I set it.
2.50 frystyk 168: ** See W. Richard Stevens (Advan. Prog. in UNIX environment, p.364)
169: ** Be CAREFULL with the old `O_NDELAY' - it will not work as read()
170: ** returns 0 when blocking and NOT -1. FNDELAY is ONLY for BSD and
171: ** does NOT work on SVR4 systems. O_NONBLOCK is POSIX.
172: */
2.74 frystyk 173: if (!net->preemptive) {
2.73 frystyk 174: #ifdef _WINSOCKAPI_
2.41 frystyk 175: { /* begin windows scope */
2.65 frystyk 176: HTRequest * rq = request;
2.41 frystyk 177: long levents = FD_READ | FD_WRITE | FD_ACCEPT |
178: FD_CONNECT | FD_CLOSE ;
179: int rv = 0 ;
180:
2.64 frystyk 181: #ifdef WWW_WIN_ASYNC
2.41 frystyk 182: /* N.B WSAAsyncSelect() turns on non-blocking I/O */
2.64 frystyk 183: rv = WSAAsyncSelect( net->sockfd, rq->hwnd,
184: rq->winMsg, levents);
185: if (rv == SOCKET_ERROR) {
186: status = -1 ;
187: if (PROT_TRACE)
2.77 eric 188: HTTrace("HTDoConnect. WSAAsyncSelect() fails: %d\n",
2.64 frystyk 189: WSAGetLastError());
190: } /* error returns */
191: #else
192: int enable = 1;
193: status = IOCTL(net->sockfd, FIONBIO, &enable);
194: #endif
2.41 frystyk 195: } /* end scope */
196: #else
197: #if defined(VMS)
2.36 frystyk 198: {
199: int enable = 1;
200: status = IOCTL(net->sockfd, FIONBIO, &enable);
201: }
202: #else
2.82 frystyk 203: if((status = fcntl(net->sockfd, F_GETFL, 0)) != -1) {
2.81 frystyk 204: #ifdef O_NONBLOCK
205: status |= O_NONBLOCK; /* POSIX */
206: #else
207: #ifdef F_NDELAY
208: status |= F_NDELAY; /* BSD */
209: #endif /* F_NDELAY */
210: #endif /* O_NONBLOCK */
2.82 frystyk 211: status = fcntl(net->sockfd, F_SETFL, status);
2.27 frystyk 212: }
2.41 frystyk 213: #endif /* VMS */
214: #endif /* WINDOW */
2.43 frystyk 215: if (PROT_TRACE) {
216: if (status == -1)
2.77 eric 217: HTTrace("HTDoConnect. Only blocking works\n");
2.43 frystyk 218: else
2.77 eric 219: HTTrace("HTDoConnect. Non-blocking socket\n");
2.43 frystyk 220: }
2.57 frystyk 221: } else if (PROT_TRACE)
2.77 eric 222: HTTrace("HTDoConnect. Blocking socket\n");
2.56 frystyk 223:
2.83 frystyk 224: /* Create a channel for this socket */
225: net->channel = HTChannel_new(net, YES);
226:
2.27 frystyk 227: /* If multi-homed host then start timer on connection */
2.55 frystyk 228: if (net->retry) net->connecttime = time(NULL);
2.65 frystyk 229:
230: /* Progress */
231: {
232: HTAlertCallback *cbf = HTAlert_find(HT_PROG_CONNECT);
233: if (cbf)
2.78 frystyk 234: (*cbf)(request,HT_PROG_CONNECT,HT_MSG_NULL,NULL,host,NULL);
2.65 frystyk 235: }
2.56 frystyk 236: net->tcpstate = TCP_NEED_CONNECT;
2.55 frystyk 237: break;
2.54 frystyk 238:
2.56 frystyk 239: case TCP_NEED_CONNECT:
2.55 frystyk 240: status = connect(net->sockfd, (struct sockaddr *) &net->sock_addr,
241: sizeof(net->sock_addr));
242: /*
243: * According to the Sun man page for connect:
244: * EINPROGRESS The socket is non-blocking and the con-
245: * nection cannot be completed immediately.
246: * It is possible to select(2) for comple-
247: * tion by selecting the socket for writ-
248: * ing.
249: * According to the Motorola SVR4 man page for connect:
250: * EAGAIN The socket is non-blocking and the con-
251: * nection cannot be completed immediately.
252: * It is possible to select for completion
253: * by selecting the socket for writing.
254: * However, this is only possible if the
255: * socket STREAMS module is the topmost
256: * module on the protocol stack with a
257: * write service procedure. This will be
258: * the normal case.
259: */
260: #ifdef _WINSOCKAPI_
261: if (status == SOCKET_ERROR)
262: #else
263: if (status < 0)
264: #endif
265: {
2.27 frystyk 266: #ifdef EAGAIN
2.55 frystyk 267: if (socerrno==EINPROGRESS || socerrno==EAGAIN)
2.41 frystyk 268: #else
2.55 frystyk 269: #ifdef _WINSOCKAPI_
270: if (socerrno==WSAEWOULDBLOCK)
2.40 frystyk 271: #else
2.55 frystyk 272: if (socerrno==EINPROGRESS)
273: #endif /* _WINSOCKAPI_ */
2.27 frystyk 274: #endif /* EAGAIN */
2.55 frystyk 275: {
276: if (PROT_TRACE)
2.77 eric 277: HTTrace("HTDoConnect. WOULD BLOCK `%s'\n",host);
2.65 frystyk 278: HTEvent_Register(net->sockfd, request, (SockOps)FD_CONNECT,
2.55 frystyk 279: net->cbf, net->priority);
2.76 frystyk 280: HT_FREE(fullhost);
2.55 frystyk 281: return HT_WOULD_BLOCK;
282: }
283: if (socerrno == EISCONN) {
284: net->tcpstate = TCP_CONNECTED;
285: break;
286: }
2.58 frystyk 287: #ifdef _WINSOCKAPI_
2.59 frystyk 288: if (socerrno == WSAEBADF) /* We lost the socket */
2.58 frystyk 289: #else
290: if (socerrno == EBADF) /* We lost the socket */
291: #endif
292: {
2.55 frystyk 293: net->tcpstate = TCP_NEED_SOCKET;
294: break;
2.27 frystyk 295: }
2.55 frystyk 296: if (net->retry) {
297: net->connecttime -= time(NULL);
2.54 frystyk 298: /* Added EINVAL `invalid argument' as this is what I
299: get back from a non-blocking connect where I should
300: get `connection refused' on BSD. SVR4 gives SIG_PIPE */
2.58 frystyk 301: #if defined(__srv4__) || defined (_WINSOCKAPI_)
2.55 frystyk 302: if (socerrno==ECONNREFUSED || socerrno==ETIMEDOUT ||
303: socerrno==ENETUNREACH || socerrno==EHOSTUNREACH ||
304: socerrno==EHOSTDOWN)
305: #else
2.54 frystyk 306: if (socerrno==ECONNREFUSED || socerrno==ETIMEDOUT ||
307: socerrno==ENETUNREACH || socerrno==EHOSTUNREACH ||
308: socerrno==EHOSTDOWN || socerrno==EINVAL)
2.35 roeber 309: #endif
2.54 frystyk 310: net->connecttime += TCP_DELAY;
311: else
312: net->connecttime += TCP_PENALTY;
2.55 frystyk 313: HTDNS_updateWeigths(net->dns, net->home, net->connecttime);
314: }
315: net->tcpstate = TCP_ERROR;
316: } else
317: net->tcpstate = TCP_CONNECTED;
318: break;
319:
320: case TCP_CONNECTED:
321: HTEvent_UnRegister(net->sockfd, (SockOps) FD_CONNECT);
322: if (net->retry) {
323: net->connecttime -= time(NULL);
2.54 frystyk 324: HTDNS_updateWeigths(net->dns, net->home, net->connecttime);
2.27 frystyk 325: }
2.55 frystyk 326: net->retry = 0;
2.82 frystyk 327: HT_FREE(fullhost);
2.55 frystyk 328: net->tcpstate = TCP_BEGIN;
329: return HT_OK;
330: break;
331:
2.56 frystyk 332: case TCP_NEED_BIND:
333: case TCP_NEED_LISTEN:
2.55 frystyk 334: case TCP_ERROR:
2.77 eric 335: if (PROT_TRACE) HTTrace("HTDoConnect. Connect failed\n");
2.55 frystyk 336: if (net->sockfd != INVSOC) {
2.53 frystyk 337: HTEvent_UnRegister(net->sockfd, (SockOps) FD_ALL);
2.55 frystyk 338: NETCLOSE(net->sockfd);
339: net->sockfd = INVSOC;
2.83 frystyk 340: if (HTHost_isPersistent(net->host)) { /* Inherited socket */
341: HTHost_clearChannel(net->host);
2.55 frystyk 342: net->tcpstate = TCP_NEED_SOCKET;
343: break;
344: }
345: }
346:
347: /* Do we have more homes to try? */
348: if (--net->retry > 0) {
2.65 frystyk 349: HTRequest_addSystemError(request, ERR_NON_FATAL, socerrno, NO,
2.55 frystyk 350: "connect");
351: net->tcpstate = TCP_DNS;
2.24 frystyk 352: break;
353: }
2.65 frystyk 354: HTRequest_addSystemError(request, ERR_FATAL,socerrno,NO,"connect");
2.55 frystyk 355: HTDNS_delete(host);
2.54 frystyk 356: net->retry = 0;
2.76 frystyk 357: HT_FREE(fullhost);
2.55 frystyk 358: net->tcpstate = TCP_BEGIN;
359: return HT_ERROR;
360: break;
2.24 frystyk 361: }
2.55 frystyk 362: }
2.13 frystyk 363: }
364:
2.56 frystyk 365: /* HTDoAccept()
366: ** ------------
367: ** This function makes a non-blocking accept which will turn up as ready
368: ** read in the select.
369: ** Returns
370: ** HT_ERROR Error has occured or interrupted
371: ** HT_OK if connected
372: ** HT_WOULD_BLOCK if operation would have blocked
2.13 frystyk 373: */
2.71 frystyk 374: PUBLIC int HTDoAccept (HTNet * net)
2.13 frystyk 375: {
376: int status;
2.56 frystyk 377: int size = sizeof(net->sock_addr);
2.65 frystyk 378: HTRequest *request = net->request;
2.36 frystyk 379: if (net->sockfd==INVSOC) {
2.77 eric 380: if (PROT_TRACE) HTTrace("HTDoAccept.. Invalid socket\n");
2.56 frystyk 381: return HT_ERROR;
2.13 frystyk 382: }
2.65 frystyk 383:
384: /* Progress report */
385: {
386: HTAlertCallback *cbf = HTAlert_find(HT_PROG_ACCEPT);
387: if (cbf) (*cbf)(request, HT_PROG_ACCEPT, HT_MSG_NULL,NULL, NULL, NULL);
388: }
2.56 frystyk 389: status = accept(net->sockfd, (struct sockaddr *) &net->sock_addr, &size);
390: #ifdef _WINSOCKAPI_
391: if (status == SOCKET_ERROR)
392: #else
393: if (status < 0)
394: #endif
2.23 duns 395: {
2.56 frystyk 396: #ifdef EAGAIN
397: if (socerrno==EINPROGRESS || socerrno==EAGAIN)
398: #else
399: #ifdef _WINSOCKAPI_
400: if (socerrno==WSAEWOULDBLOCK)
401: #else
402: if (socerrno==EINPROGRESS)
403: #endif /* _WINSOCKAPI_ */
404: #endif /* EAGAIN */
405: {
406: if (PROT_TRACE)
2.77 eric 407: HTTrace("HTDoAccept.. WOULD BLOCK %d\n", net->sockfd);
2.65 frystyk 408: HTEvent_Register(net->sockfd, request, (SockOps) FD_ACCEPT,
2.56 frystyk 409: net->cbf, net->priority);
410: return HT_WOULD_BLOCK;
411: }
2.65 frystyk 412: HTRequest_addSystemError(request, ERR_WARN, socerrno, YES, "accept");
2.77 eric 413: if (PROT_TRACE) HTTrace("HTDoAccept.. Accept failed\n");
2.56 frystyk 414: return HT_ERROR;
2.23 duns 415: }
2.71 frystyk 416:
417: /* Swap to new socket */
418: HTEvent_UnRegister(net->sockfd, (SockOps) FD_ACCEPT);
419: net->sockfd = status;
2.83 frystyk 420:
421: /* Create a channel for the new socket */
422: net->channel = HTChannel_new(net, NO);
423:
2.77 eric 424: if (PROT_TRACE) HTTrace("Accepted.... socket %d\n", status);
2.56 frystyk 425: return HT_OK;
426: }
427:
428:
429: /* HTDoListen
430: ** ----------
431: ** Listens on the specified port. 0 means that we chose it here
432: ** If master==INVSOC then we listen on all local interfaces (using a
433: ** wildcard). If !INVSOC then use this as the local interface
434: ** returns HT_ERROR Error has occured or interrupted
435: ** HT_OK if connected
436: */
2.67 frystyk 437: PUBLIC int HTDoListen (HTNet * net, u_short port, SOCKET master, int backlog)
2.56 frystyk 438: {
439: int status;
440:
441: /* Jump into the state machine */
442: while (1) {
443: switch (net->tcpstate) {
444: case TCP_BEGIN:
445: {
446: SockA *sin = &net->sock_addr;
447: memset((void *) sin, '\0', sizeof(SockA));
448: #ifdef DECNET
449: sin->sdn_family = AF_DECnet;
450: sin->sdn_objnum = port;
2.36 frystyk 451: #else
2.56 frystyk 452: sin->sin_family = AF_INET;
453: if (master != INVSOC) {
454: int len = sizeof(SockA);
455: if (getsockname(master, (struct sockaddr *) sin, &len)<0) {
2.65 frystyk 456: HTRequest_addSystemError(net->request, ERR_FATAL,
457: socerrno, NO, "getsockname");
2.56 frystyk 458: net->tcpstate = TCP_ERROR;
459: break;
460: }
461: } else
462: sin->sin_addr.s_addr = INADDR_ANY;
463: sin->sin_port = htons(port);
464: #endif
465: }
466: if (PROT_TRACE)
2.83 frystyk 467: HTTrace("Socket...... Listen on port %d\n", port);
2.56 frystyk 468: net->tcpstate = TCP_NEED_SOCKET;
469: break;
470:
471: case TCP_NEED_SOCKET:
472: #ifdef DECNET
473: if ((net->sockfd=socket(AF_DECnet, SOCK_STREAM, 0))==INVSOC)
474: #else
475: if ((net->sockfd=socket(AF_INET, SOCK_STREAM,IPPROTO_TCP))==INVSOC)
476: #endif
477: {
2.65 frystyk 478: HTRequest_addSystemError(net->request, ERR_FATAL, socerrno,
479: NO, "socket");
2.56 frystyk 480: net->tcpstate = TCP_ERROR;
481: break;
482: }
483: if (PROT_TRACE)
2.83 frystyk 484: HTTrace("Socket...... Created %d\n", net->sockfd);
2.56 frystyk 485:
486: /* If non-blocking protocol then change socket status
2.82 frystyk 487: ** I use fcntl() so that I can ask the status before I set it.
2.56 frystyk 488: ** See W. Richard Stevens (Advan. Prog. in UNIX environment, p.364)
489: ** Be CAREFULL with the old `O_NDELAY' - it will not work as read()
490: ** returns 0 when blocking and NOT -1. FNDELAY is ONLY for BSD and
491: ** does NOT work on SVR4 systems. O_NONBLOCK is POSIX.
492: */
2.74 frystyk 493: if (!net->preemptive) {
2.73 frystyk 494: #ifdef _WINSOCKAPI_
2.56 frystyk 495: { /* begin windows scope */
496: long levents = FD_READ | FD_WRITE | FD_ACCEPT |
497: FD_CONNECT | FD_CLOSE ;
498: int rv = 0 ;
499:
2.64 frystyk 500: #ifdef WWW_WIN_ASYNC
2.56 frystyk 501: /* N.B WSAAsyncSelect() turns on non-blocking I/O */
2.69 frystyk 502: rv = WSAAsyncSelect(net->sockfd, net->request->hwnd,
2.66 frystyk 503: net->request->winMsg, levents);
2.64 frystyk 504: if (rv == SOCKET_ERROR) {
505: status = -1 ;
506: if (PROT_TRACE)
2.83 frystyk 507: HTTrace("Socket...... WSAAsyncSelect() fails: %d\n",
2.64 frystyk 508: WSAGetLastError());
2.56 frystyk 509: } /* error returns */
2.64 frystyk 510: #else
511: int enable = 1 ;
512: status = IOCTL(net->sockfd, FIONBIO, &enable);
513: #endif
2.56 frystyk 514: } /* end scope */
515: #else
516: #if defined(VMS)
517: {
518: int enable = 1;
519: status = IOCTL(net->sockfd, FIONBIO, &enable);
520: }
521: #else
2.82 frystyk 522: if((status = fcntl(net->sockfd, F_GETFL, 0)) != -1) {
2.81 frystyk 523: #ifdef O_NONBLOCK
2.56 frystyk 524: status |= O_NONBLOCK; /* POSIX */
2.81 frystyk 525: #else
526: #ifdef F_NDELAY
527: status |= F_NDELAY; /* BSD */
528: #endif /* F_NDELAY */
529: #endif /* O_NONBLOCK */
2.82 frystyk 530: status = fcntl(net->sockfd, F_SETFL, status);
2.56 frystyk 531: }
532: #endif /* VMS */
533: #endif /* WINDOW */
534: if (PROT_TRACE) {
535: if (status == -1)
2.83 frystyk 536: HTTrace("Sockrt...... Blocking socket\n");
2.56 frystyk 537: else
2.83 frystyk 538: HTTrace("Socket...... Non-blocking socket\n");
2.56 frystyk 539: }
540: }
541: net->tcpstate = TCP_NEED_BIND;
542: break;
543:
544: case TCP_NEED_BIND:
545: status = bind(net->sockfd, (struct sockaddr *) &net->sock_addr,
546: sizeof(net->sock_addr));
547: #ifdef _WINSOCKAPI_
548: if (status == SOCKET_ERROR)
549: #else
550: if (status < 0)
551: #endif
552: {
553: if (PROT_TRACE)
2.83 frystyk 554: HTTrace("Socket...... Bind failed %d\n", socerrno);
2.56 frystyk 555: net->tcpstate = TCP_ERROR;
556: } else
557: net->tcpstate = TCP_NEED_LISTEN;
558: break;
559:
560: case TCP_NEED_LISTEN:
2.67 frystyk 561: status = listen(net->sockfd, backlog);
2.56 frystyk 562: #ifdef _WINSOCKAPI_
563: if (status == SOCKET_ERROR)
564: #else
565: if (status < 0)
2.36 frystyk 566: #endif
2.56 frystyk 567: net->tcpstate = TCP_ERROR;
568: else
569: net->tcpstate = TCP_CONNECTED;
570: break;
571:
572: case TCP_CONNECTED:
573: net->tcpstate = TCP_BEGIN;
574: if (PROT_TRACE)
2.83 frystyk 575: HTTrace("Socket...... Bind and listen on port %d %s\n",
2.56 frystyk 576: (int) ntohs(net->sock_addr.sin_port),
577: HTInetString(&net->sock_addr));
578: return HT_OK;
579: break;
2.13 frystyk 580:
2.56 frystyk 581: case TCP_NEED_CONNECT:
582: case TCP_DNS:
583: case TCP_ERROR:
2.83 frystyk 584: if (PROT_TRACE) HTTrace("Socket...... Listen failed\n");
2.62 frystyk 585: HTRequest_addSystemError(net->request, ERR_FATAL, socerrno, NO, "HTDoListen");
2.56 frystyk 586: net->tcpstate = TCP_BEGIN;
587: return HT_ERROR;
588: break;
589: }
2.38 frystyk 590: }
1.1 timbl 591: }
592:
2.83 frystyk 593: /* HTDoClose
594: ** ---------
595: ** Closes a file descriptor whatever means are available on the current
596: ** platform. If we have unix file descriptors then use this otherwise use
597: ** the ANSI C file descriptors
598: **
599: ** returns HT_ERROR Error has occured or interrupted
600: ** HT_OK if connected
601: ** HT_WOULD_BLOCK if operation would have blocked
602: */
603: PUBLIC int HTDoCLose (HTNet * net)
604: {
605: int status = -1;
606: if (net && net->sockfd != INVSOC) {
607: if (PROT_TRACE) HTTrace("Socket...... Close %d\n", net->sockfd);
608: status = NETCLOSE(net->sockfd);
609: HTEvent_UnRegister(net->sockfd, (SockOps) FD_ALL);
610: net->sockfd = INVSOC;
611: }
612: return status < 0 ? HT_ERROR : HT_OK;
613: }
614:
Webmaster