Annotation of libwww/Library/src/HTTCP.c, revision 2.13
1.1 timbl 1: /* Generic Communication Code HTTCP.c
2: ** ==========================
3: **
4: ** This code is in common between client and server sides.
5: **
6: ** 16 Jan 92 TBL Fix strtol() undefined on CMU Mach.
7: ** 25 Jun 92 JFG Added DECNET option through TCP socket emulation.
2.7 duns 8: ** 13 Sep 93 MD Added correct return of vmserrorno for HTInetStatus.
9: ** Added decoding of vms error message for MULTINET.
2.13 ! frystyk 10: ** 31 May 94 HF Added cache on host id's; now use inet_ntoa() to
! 11: ** HTInetString and some other fixes. Added HTDoConnect
! 12: ** and HTDoAccept
1.1 timbl 13: */
14:
2.13 ! frystyk 15: #include "tcp.h" /* Defines SHORT_NAMES if necessary */
! 16: #include "HTUtils.h"
! 17: #include "HTAtom.h"
! 18: #include "HTList.h"
! 19: #include "HTParse.h"
! 20: #include "HTAccess.h"
! 21: #include "HTError.h"
1.1 timbl 22:
23: #ifdef SHORT_NAMES
24: #define HTInetStatus HTInStat
2.12 luotonen 25: #define HTErrnoString HTErrnoS
1.1 timbl 26: #define HTInetString HTInStri
27: #define HTParseInet HTPaInet
28: #endif
29:
2.8 luotonen 30:
2.11 duns 31: /* VMS stuff */
32: #ifdef VMS
33: #ifndef MULTINET
34: #define FD_SETSIZE 32
35: #else /* Multinet */
36: #define FD_SETSIZE 256
37: #endif /* Multinet */
38: #endif /* VMS */
39:
2.13 ! frystyk 40: /* Macros and other defines */
! 41: #define MAX_ACCEPT_POLL 30
! 42: #define FCNTL(r, s, t) fcntl(r, s, t)
! 43:
! 44: /* Globals */
! 45: PUBLIC unsigned int HTConCacheSize = 512; /* Number of cached servers */
! 46:
! 47: /* Type definitions and global variables etc. local to this module */
! 48:
! 49: /* This structure is a cache of hosts to whom we have connected over time.
! 50: The structure contains the necessary parts from hostent. For Internet host
! 51: hostent->h_addr_list is not an array of char pointers but an array of
! 52: pointers of type in_addr. */
! 53: typedef struct _host_info {
! 54: HTAtom * hostname; /* Official name of host */
! 55: int hits; /* Total number of hits on this host */
! 56: int addrlength; /* Length of address in bytes */
! 57: int multihomed; /* Number of IP addresses on the host */
! 58: int offset; /* Offset value of active IP address */
! 59: char ** addrlist; /* List of addresses from name server */
! 60: float * weight; /* Weight on each address */
! 61: } host_info;
! 62:
! 63: PRIVATE char *hostname = NULL; /* The name of this host */
! 64: PRIVATE HTList *hostcache = NULL; /* List of servers that we have talked to */
! 65: PRIVATE unsigned int HTCacheSize = 0; /* Current size of cache */
2.11 duns 66:
2.13 ! frystyk 67: /* ------------------------------------------------------------------------- */
1.1 timbl 68:
69: /* Encode INET status (as in sys/errno.h) inet_status()
70: ** ------------------
71: **
72: ** On entry,
73: ** where gives a description of what caused the error
74: ** global errno gives the error number in the unix way.
75: **
76: ** On return,
77: ** returns a negative status in the unix way.
78: */
79: #ifndef PCNFS
2.7 duns 80: #ifdef VMS
2.10 duns 81: #ifndef __DECC
1.1 timbl 82: extern int uerrno; /* Deposit of error info (as per errno.h) */
2.7 duns 83: extern volatile noshare int socket_errno; /* socket VMS error info
84: (used for translation of vmserrno) */
1.1 timbl 85: extern volatile noshare int vmserrno; /* Deposit of VMS error info */
86: extern volatile noshare int errno; /* noshare to avoid PSECT conflict */
2.10 duns 87: #endif /* not DECC */
2.11 duns 88: #endif /* VMS */
89:
1.1 timbl 90: #ifndef errno
91: extern int errno;
92: #endif /* errno */
93:
94: #ifndef VM
2.7 duns 95: #ifndef VMS
1.1 timbl 96: #ifndef NeXT
97: #ifndef THINK_C
98: extern char *sys_errlist[]; /* see man perror on cernvax */
99: extern int sys_nerr;
100: #endif /* think c */
101: #endif /* NeXT */
2.7 duns 102: #endif /* VMS */
1.1 timbl 103: #endif /* VM */
104:
105: #endif /* PCNFS */
106:
2.12 luotonen 107:
108: /*
109: * Returns the string equivalent of the current errno.
110: */
111: PUBLIC CONST char * HTErrnoString NOARGS
1.1 timbl 112: {
2.11 duns 113: #ifndef VMS
2.7 duns 114:
1.1 timbl 115: #ifdef VM
2.12 luotonen 116: return "(Error number not translated)"; /* What Is the VM equiv? */
1.1 timbl 117: #define ER_NO_TRANS_DONE
118: #endif
2.12 luotonen 119:
120: #if defined(NeXT) || defined(THINK_C)
121: return strerror(errno);
1.1 timbl 122: #define ER_NO_TRANS_DONE
123: #endif
2.12 luotonen 124:
125: #ifndef ER_NO_TRANS_DONE
126: return (errno < sys_nerr ? sys_errlist[errno] : "Unknown error");
1.1 timbl 127: #endif
128:
2.12 luotonen 129: #else /* VMS */
130:
131: static char buf[60];
132: sprintf(buf,"Unix errno = %ld dec, VMS error = %lx hex",errno,vaxc$errno);
133: return buf;
134:
1.1 timbl 135: #endif
2.12 luotonen 136: }
137:
138:
139: /* Report Internet Error
140: ** ---------------------
141: */
142: PUBLIC int HTInetStatus ARGS1(char *, where)
143: {
144: #ifndef VMS
145:
146: CTRACE(tfp,
147: "TCP errno... %d after call to %s() failed.\n............ %s\n",
148: errno, where, HTErrnoString());
1.1 timbl 149:
2.11 duns 150: #else /* VMS */
2.12 luotonen 151:
2.11 duns 152: CTRACE(tfp, " Unix error number = %ld dec\n", errno);
153: CTRACE(tfp, " VMS error = %lx hex\n", vaxc$errno);
2.12 luotonen 154:
2.11 duns 155: #ifdef MULTINET
156: CTRACE(tfp, " Multinet error = %lx hex\n", socket_errno);
157: #endif /* MULTINET */
2.12 luotonen 158:
2.11 duns 159: #endif /* VMS */
2.7 duns 160:
161: #ifdef VMS
2.11 duns 162: /* errno happen to be zero if vaxc$errno <> 0 */
163: return -vaxc$errno;
2.7 duns 164: #else
1.1 timbl 165: return -errno;
2.7 duns 166: #endif
1.1 timbl 167: }
168:
169:
170: /* Parse a cardinal value parse_cardinal()
171: ** ----------------------
172: **
173: ** On entry,
174: ** *pp points to first character to be interpreted, terminated by
175: ** non 0:9 character.
176: ** *pstatus points to status already valid
177: ** maxvalue gives the largest allowable value.
178: **
179: ** On exit,
180: ** *pp points to first unread character
181: ** *pstatus points to status updated iff bad
182: */
183:
184: PUBLIC unsigned int HTCardinal ARGS3
185: (int *, pstatus,
186: char **, pp,
187: unsigned int, max_value)
188: {
189: int n;
190: if ( (**pp<'0') || (**pp>'9')) { /* Null string is error */
191: *pstatus = -3; /* No number where one expeceted */
192: return 0;
193: }
194:
195: n=0;
196: while ((**pp>='0') && (**pp<='9')) n = n*10 + *((*pp)++) - '0';
197:
198: if (n>max_value) {
199: *pstatus = -4; /* Cardinal outside range */
200: return 0;
201: }
202:
203: return n;
204: }
205:
206:
207: #ifndef DECNET /* Function only used below for a trace message */
208:
209: /* Produce a string for an Internet address
210: ** ----------------------------------------
211: **
212: ** On exit,
213: ** returns a pointer to a static string which must be copied if
214: ** it is to be kept.
215: */
216:
2.13 ! frystyk 217: PUBLIC CONST char * HTInetString ARGS1(SockA *, sin)
1.1 timbl 218: {
2.13 ! frystyk 219: return inet_ntoa(sin->sin_addr);
! 220: #ifdef OLD_CODE
1.1 timbl 221: static char string[16];
222: sprintf(string, "%d.%d.%d.%d",
223: (int)*((unsigned char *)(&sin->sin_addr)+0),
224: (int)*((unsigned char *)(&sin->sin_addr)+1),
225: (int)*((unsigned char *)(&sin->sin_addr)+2),
226: (int)*((unsigned char *)(&sin->sin_addr)+3));
2.13 ! frystyk 227: #endif
1.1 timbl 228: }
229: #endif /* Decnet */
230:
231:
2.13 ! frystyk 232: /* HTTCPCacheRemoveElement
! 233: **
! 234: ** Remove the element specified from the cache
! 235: */
! 236: PRIVATE void HTTCPCacheRemoveElement ARGS1(host_info *, element)
! 237: {
! 238: if (!hostcache) {
! 239: if (TRACE)
! 240: fprintf(stderr, "HostCache... Remove not done, no cache\n");
! 241: return;
! 242: }
! 243: if (TRACE) fprintf(stderr, "HostCache... Remove `%s' from cache\n",
! 244: HTAtom_name(element->hostname));
! 245: HTList_removeObject(hostcache, element);
! 246: if (element->addrlist)
! 247: free(element->addrlist);
! 248: if (element->weight)
! 249: free(element->weight);
! 250: free(element);
! 251: }
! 252:
! 253:
! 254: /* HTTCPCacheRemoveHost
! 255: **
! 256: ** Removes the corresponding entrance in the cache
! 257: */
! 258: PRIVATE void HTTCPCacheRemoveHost ARGS1(char *, host)
! 259: {
! 260: HTAtom *hostatom = HTAtom_for(host);
! 261: HTList *cur = hostcache;
! 262: host_info *pres = NULL;
! 263: if (!hostcache) {
! 264: fprintf(stderr, "HostCache... Remove host not done, no cache\n");
! 265: return;
! 266: }
! 267: while ((pres = (host_info *) HTList_nextObject(cur)) != NULL) {
! 268: if (pres->hostname == hostatom) {
! 269: break;
! 270: }
! 271: }
! 272: if (pres)
! 273: HTTCPCacheRemoveElement(pres);
! 274: }
! 275:
! 276:
! 277: /* HTTCPCacheGarbage
! 278: **
! 279: ** Remove the element with the lowest hit rate
! 280: */
! 281: PRIVATE void HTTCPCacheGarbage NOARGS
! 282: {
! 283: HTList *cur = hostcache;
! 284: host_info *pres, *worst_match = NULL;
! 285: unsigned int worst_hits = 30000; /* Should use UINT_MAX :-( */
! 286: if (!hostcache) {
! 287: if (TRACE)
! 288: fprintf(stderr, "HostCache... Garbage collection not done, no cache\n");
! 289: return;
! 290: }
! 291:
! 292: /* Seek for worst element */
! 293: while ((pres = (host_info *) HTList_nextObject(cur))) {
! 294: if (!worst_match || pres->hits <= worst_hits) {
! 295: worst_match = pres;
! 296: worst_hits = pres->hits;
! 297: }
! 298: }
! 299: if (worst_match)
! 300: HTTCPCacheRemoveElement(worst_match);
! 301: }
! 302:
! 303:
! 304: /* HTTCPCacheAddElement
! 305: **
! 306: ** Add an element to the cache of visited hosts. Note that this function
! 307: ** requires the system implemented structure hostent and not our own
! 308: ** host_info. If multihomed host then multihome indicates the number of
! 309: ** IP addresses found. If not then multihome=0
! 310: **
! 311: ** Returns new element if OK NULL if error
! 312: */
! 313: PRIVATE host_info *HTTCPCacheAddElement ARGS2(HTAtom *, host,
! 314: struct hostent *, element)
! 315: {
! 316: int homes; /* Number of homes on the host */
! 317: host_info *new;
! 318: if (!host || !element) {
! 319: if (TRACE)
! 320: fprintf(stderr, "HostCache... Bad argument to add to cache\n");
! 321: return NULL;
! 322: }
! 323: if ((new = (host_info *) calloc(1, sizeof(host_info))) == NULL ||
! 324: (new->addrlist = (char **)
! 325: calloc(1, sizeof element->h_addr_list)) == NULL)
! 326: outofmem(__FILE__, "HTParseInet");
! 327: new->hostname = host;
! 328:
! 329: if ((homes = (sizeof element->h_addr_list) / element->h_length) > 1) {
! 330: new->multihomed = homes;
! 331: if ((new->weight = (float *) calloc(homes, sizeof(float))) == NULL)
! 332: outofmem(__FILE__, "HTTCPCacheAddElement");
! 333: }
! 334: new->addrlength = element->h_length;
! 335: memcpy((void *) new->addrlist, element->h_addr_list,
! 336: sizeof element->h_addr_list);
! 337: if (!hostcache)
! 338: hostcache = HTList_new();
! 339:
! 340: if (TRACE) {
! 341: if (new->multihomed)
! 342: fprintf(stderr, "HostCache... Adding multihomed host `%s' having %d homes\n", HTAtom_name(host), new->multihomed);
! 343: else
! 344: fprintf(stderr, "HostCache... Adding `%s'\n", HTAtom_name(host));
! 345: }
! 346: HTList_addObject(hostcache, (void *) new);
! 347: HTCacheSize++; /* Update number of elements */
! 348: return new;
! 349: }
! 350:
! 351:
! 352: /* HTTCPAddrWeights
! 353: **
! 354: ** This function calculates the weights of the different IP addresses
! 355: ** on a multi homed host. Each weight is calculated as
! 356: **
! 357: ** w(n+1) = w(n)*a + (1-a) * deltatime
! 358: ** a = exp(-1/Neff)
! 359: ** Neff is the effective number of samples used
! 360: ** deltatime is time spend on making a connection
! 361: **
! 362: ** A short window (low Neff) gives a high sensibility, but this is
! 363: ** required as we can't expect a lot of data to test on.
! 364: **
! 365: */
! 366: PUBLIC void HTTCPAddrWeights ARGS2(char *, host, time_t, deltatime)
! 367: {
! 368: HTAtom *hostatom = HTAtom_for(host);
! 369: HTList *cur = hostcache;
! 370: host_info *pres = NULL;
! 371: if (!hostcache) {
! 372: fprintf(stderr, "HostCache... Weights not calculated, no cache\n");
! 373: return;
! 374: }
! 375: while ((pres = (host_info *) HTList_nextObject(cur)) != NULL) {
! 376: if (pres->hostname == hostatom) {
! 377: break;
! 378: }
! 379: }
! 380: if (pres && pres->multihomed) {
! 381: int cnt;
! 382: const float passive = 0.9; /* Factor for all passive IP_addrs */
! 383: #if 0
! 384: const int Neff = 3;
! 385: const float alpha = exp(-1.0/Neff);
! 386: #else
! 387: const float alpha = 0.716531310574;
! 388: #endif
! 389: for (cnt=0; cnt<pres->multihomed; cnt++) {
! 390: if (cnt == pres->offset) {
! 391: *(pres->weight+pres->offset) = *(pres->weight+pres->offset)*alpha + (1.0-alpha)*deltatime;
! 392: } else {
! 393: *(pres->weight+cnt) = *(pres->weight+cnt) * passive;
! 394: }
! 395: }
! 396: } else if (TRACE) {
! 397: fprintf(stderr, "HostCache... Weights not calculated, host not found in cache or is not multihomed: `%s\'\n", host);
! 398: }
! 399: }
! 400:
! 401:
! 402: /* HTGetHostByName
! 403: **
! 404: ** Searched first the local cache then asks the DNS for an address of
! 405: ** the host specified.
! 406: **
! 407: ** Returns 0 if OK else -1
! 408: */
! 409: PUBLIC int HTGetHostByName ARGS3(char *, host, SockA *, sin, BOOL *, multi)
! 410: {
! 411: HTAtom *hostatom = HTAtom_for(host);
! 412: host_info *pres = NULL;
! 413: if (!hostcache)
! 414: hostcache = HTList_new(); /* First time through */
! 415: else {
! 416: HTList *cur = hostcache; /* Search cache */
! 417: while ((pres = (host_info *) HTList_nextObject(cur)) != NULL) {
! 418: if (pres->hostname == hostatom) {
! 419: if (TRACE)
! 420: fprintf(stderr, "ParseInet... Host `%s\' found in cache.\n", host);
! 421: break;
! 422: }
! 423: }
! 424: }
! 425:
! 426: /* If the host was not found in the cache, then do gethostbyname.
! 427: If cache found then find the best address if more than one. If we
! 428: are talking to a multi homed host then take the IP address with the
! 429: lowest weight */
! 430: if (pres) {
! 431: if (pres->multihomed) {
! 432: int cnt;
! 433: float best_weight = 1e30; /* Should be FLT_MAX :-( */
! 434: for (cnt=0; cnt<pres->multihomed; cnt++) {
! 435: if (*(pres->weight+cnt) < best_weight) {
! 436: best_weight = *(pres->weight+cnt);
! 437: pres->offset = cnt;
! 438: }
! 439: }
! 440: *multi = YES;
! 441: } else
! 442: *multi = NO;
! 443: pres->hits++; /* Update number of hits */
! 444: } else { /* Go and ask for it */
! 445: struct hostent *hostelement; /* see netdb.h */
! 446: #ifdef MVS /* Outstanding problem with crash in MVS gethostbyname */
! 447: if (TRACE)
! 448: fprintf(stderr, "HTTCP: gethostbyname(%s)\n", host);
! 449: #endif
! 450: if ((hostelement = gethostbyname(host)) == NULL) {
! 451: if (TRACE) fprintf(stderr, "ParseInet... Can't find internet node name `%s'.\n", host);
! 452: return -1;
! 453: }
! 454:
! 455: /* Add element to the cache and maybe do garbage collection */
! 456: if (HTCacheSize >= HTConCacheSize)
! 457: HTTCPCacheGarbage();
! 458: if ((pres = HTTCPCacheAddElement(hostatom, hostelement)) == NULL) {
! 459: return -1;
! 460: }
! 461: }
! 462:
! 463: /* Update socket structure using the element with the lowest weight. On
! 464: single homed hosts it means the first value */
! 465: memcpy(&sin->sin_addr, *(pres->addrlist+pres->offset), pres->addrlength);
! 466: return 0;
! 467: }
! 468:
! 469:
1.1 timbl 470: /* Parse a network node address and port
471: ** -------------------------------------
472: **
473: ** On entry,
474: ** str points to a string with a node name or number,
475: ** with optional trailing colon and port number.
476: ** sin points to the binary internet or decnet address field.
477: **
478: ** On exit,
479: ** *sin is filled in. If no port is specified in str, that
480: ** field is left unchanged in *sin.
2.13 ! frystyk 481: **
! 482: ** NOTE: It is assumed that any portnumber and numeric host address
! 483: ** is given in decimal notation. Separation character is '.'
1.1 timbl 484: */
2.13 ! frystyk 485: PUBLIC int HTParseInet ARGS3(SockA *,sin, CONST char *,str, BOOL *, multihome)
1.1 timbl 486: {
2.13 ! frystyk 487: char *host = NULL;
! 488: StrAllocCopy(host, str); /* Take a copy we can mutilate */
1.1 timbl 489:
2.13 ! frystyk 490: /* Parse port number if present. */
! 491: *multihome = NO;
! 492: {
! 493: char *port;
! 494: if ((port=strchr(host, ':'))) {
! 495: *port++ = 0; /* Chop off port */
! 496: if (isdigit(*port)) {
1.1 timbl 497: #ifdef DECNET
2.13 ! frystyk 498: sin->sdn_objnum = (unsigned char)(strtol(port, (char**)0, 10));
! 499: #else /* Internet */
! 500: sin->sin_port = htons(atol(port));
1.1 timbl 501: #endif
2.13 ! frystyk 502: } else {
! 503: fprintf(stderr, "ParseInet... No port indicated\n");
! 504: }
1.1 timbl 505: }
2.13 ! frystyk 506: }
1.1 timbl 507:
2.13 ! frystyk 508: /* Parse Internet host */
1.1 timbl 509: #ifdef DECNET
510: /* read Decnet node name. @@ Should know about DECnet addresses, but it's
511: probably worth waiting until the Phase transition from IV to V. */
512:
513: sin->sdn_nam.n_len = min(DN_MAXNAML, strlen(host)); /* <=6 in phase 4 */
514: strncpy (sin->sdn_nam.n_name, host, sin->sdn_nam.n_len + 1);
515:
516: if (TRACE) fprintf(stderr,
517: "DECnet: Parsed address as object number %d on host %.6s...\n",
518: sin->sdn_objnum, host);
519:
2.13 ! frystyk 520: #else /* Internet */
1.1 timbl 521:
2.13 ! frystyk 522: /* Parse host number if present */
! 523: {
! 524: BOOL numeric = YES;
! 525: char *strptr = host;
! 526: while (*strptr) {
! 527: if (!isdigit(*strptr) && *strptr != '.') {
! 528: numeric = NO;
! 529: break;
! 530: }
! 531: ++strptr;
! 532: }
! 533: if (numeric) {
! 534: sin->sin_addr.s_addr = inet_addr(host); /* See arpa/inet.h */
! 535: } else {
! 536: if (HTGetHostByName(host, sin, multihome)) {
! 537: free(host);
! 538: return -1;
! 539: }
! 540: }
! 541: if (TRACE) {
! 542: fprintf(stderr, "ParseInet... Parsed address as port %d on %s\n",
! 543: (int) ntohs(sin->sin_port),
! 544: HTInetString(sin));
1.1 timbl 545: }
546: }
547: #endif /* Internet vs. Decnet */
2.13 ! frystyk 548: free(host);
1.1 timbl 549: return 0; /* OK */
550: }
551:
552:
2.8 luotonen 553: /*
554: ** Get host name of the machine on the other end of a socket.
2.13 ! frystyk 555: ** THIS SHOULD BE CALLED HTGetHostByAddr :-(
2.8 luotonen 556: */
557: PUBLIC char * HTGetHostName ARGS1(int, soc)
558: {
559: struct sockaddr addr;
560: int len = sizeof(struct sockaddr);
561: struct in_addr *iaddr;
562: struct hostent * phost; /* Pointer to host -- See netdb.h */
563: char *name = NULL;
564:
565: #ifdef DECNET /* Decnet ain't got no damn name server 8#OO */
566: return NULL;
567: #else
568: if (getpeername(soc, &addr, &len) < 0)
569: return NULL;
570:
571: iaddr = &(((struct sockaddr_in *)&addr)->sin_addr);
572: phost=gethostbyaddr((char*)iaddr,
573: sizeof(struct in_addr),
574: AF_INET);
575: if (!phost) {
576: if (TRACE) fprintf(stderr,
2.9 luotonen 577: "TCP......... Can't find internet node name for peer!!\n");
2.8 luotonen 578: return NULL;
579: }
580: StrAllocCopy(name, phost->h_name);
2.9 luotonen 581: if (TRACE) fprintf(stderr, "TCP......... Peer name is `%s'\n", name);
2.8 luotonen 582:
583: return name;
584:
585: #endif /* not DECNET */
586: }
587:
588:
1.1 timbl 589: /* Derive the name of the host on which we are
590: ** -------------------------------------------
591: **
592: */
2.8 luotonen 593: PRIVATE void get_host_details NOARGS
1.1 timbl 594:
595: #ifndef MAXHOSTNAMELEN
596: #define MAXHOSTNAMELEN 64 /* Arbitrary limit */
597: #endif
598:
599: {
600: char name[MAXHOSTNAMELEN+1]; /* The name of this host */
601: struct hostent * phost; /* Pointer to host -- See netdb.h */
602: int namelength = sizeof(name);
603:
604: if (hostname) return; /* Already done */
605: gethostname(name, namelength); /* Without domain */
2.9 luotonen 606: CTRACE(tfp, "TCP......... Local host name is %s\n", name);
1.1 timbl 607: StrAllocCopy(hostname, name);
608:
609: #ifndef DECNET /* Decnet ain't got no damn name server 8#OO */
610: phost=gethostbyname(name); /* See netdb.h */
611: if (!phost) {
612: if (TRACE) fprintf(stderr,
2.9 luotonen 613: "TCP......... Can't find my own internet node address for `%s'!!\n",
1.1 timbl 614: name);
615: return; /* Fail! */
616: }
617: StrAllocCopy(hostname, phost->h_name);
2.9 luotonen 618: CTRACE(tfp, "TCP......... Full local host name is %s\n", hostname);
2.8 luotonen 619:
620: #ifdef NEED_HOST_ADDRESS /* no -- needs name server! */
1.1 timbl 621: memcpy(&HTHostAddress, &phost->h_addr, phost->h_length);
622: if (TRACE) fprintf(stderr, " Name server says that I am `%s' = %s\n",
623: hostname, HTInetString(&HTHostAddress));
2.8 luotonen 624: #endif /* NEED_HOST_ADDRESS */
1.1 timbl 625:
626: #endif /* not Decnet */
627: }
628:
2.12 luotonen 629:
630: PUBLIC CONST char * HTHostName NOARGS
1.1 timbl 631: {
632: get_host_details();
633: return hostname;
2.13 ! frystyk 634: }
! 635:
! 636:
! 637: /* HTDoConnect()
! 638: **
! 639: ** TEMPORARY FUNCTION.
! 640: ** Note: Any port indication in URL, e.g., as `host:port' overwrites
! 641: ** the default_port value.
! 642: **
! 643: ** Returns 0 if OK, -1 on error
! 644: */
! 645: PUBLIC int HTDoConnect ARGS5(HTRequest *, request, char *, url,
! 646: u_short, default_port, int *, sockfd,
! 647: u_long *, addr)
! 648: {
! 649: BOOL multihomed = NO;
! 650: time_t deltatime;
! 651: int status;
! 652: SockA sock_addr; /* SockA is defined in tcp.h */
! 653: char *p1 = HTParse(url, "", PARSE_HOST);
! 654: char *at_sign;
! 655: char *host;
! 656:
! 657: /* if theres an @ then use the stuff after it as a hostname */
! 658: if((at_sign = strchr(p1,'@')) != NULL)
! 659: host = at_sign+1;
! 660: else
! 661: host = p1;
! 662: if (TRACE) fprintf(stderr, "HTDoConnect. Looking up `%s\'\n", host);
! 663:
! 664: /* Set up defaults */
! 665: memset((void *) &sock_addr, '\0', sizeof(sock_addr));
! 666: #ifdef DECNET
! 667: sock_addr.sdn_family = AF_DECnet; /* Family = DECnet, host order */
! 668: sock_addr.sdn_objnum = DNP_OBJ; /* Default: http object number */
! 669: #else /* Internet */
! 670: sock_addr.sin_family = AF_INET;
! 671: sock_addr.sin_port = htons(default_port);
! 672: #endif
! 673:
! 674: /* Get node name */
! 675: if (HTParseInet(&sock_addr, host, &multihomed)) {
! 676: if (TRACE) fprintf(stderr, "HTDoConnect. Can't locate remote host `%s\'\n", host);
! 677: HTErrorAdd(request, ERR_FATAL, NO, HTERR_NO_REMOTE_HOST,
! 678: (void *) host, strlen(host), "HTDoConnect");
! 679: free (p1);
! 680: *sockfd = -1;
! 681: return -1;
! 682: }
! 683:
! 684: #ifdef DECNET
! 685: if ((*sockfd = socket(AF_DECnet, SOCK_STREAM, 0)) < 0) {
! 686: #else
! 687: if ((*sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
! 688: #endif
! 689: HTErrorSysAdd(request, ERR_FATAL, NO, "socket");
! 690: free (p1);
! 691: return -1;
! 692: }
! 693: if (addr)
! 694: *addr = ntohl(sock_addr.sin_addr.s_addr);
! 695:
! 696: if (TRACE)
! 697: fprintf(stderr, "HTDoConnect. Created socket number %d\n", *sockfd);
! 698:
! 699: if (multihomed) /* Start timer on connection */
! 700: deltatime = time(NULL);
! 701: if ((status = connect(*sockfd, (struct sockaddr *) &sock_addr,
! 702: sizeof(sock_addr))) < 0) {
! 703: HTErrorSysAdd(request, ERR_FATAL, NO, "connect");
! 704: HTTCPCacheRemoveHost(host); /* Remove host from cache */
! 705: if (NETCLOSE(*sockfd) < 0)
! 706: HTErrorSysAdd(request, ERR_FATAL, NO, "close");
! 707: free(p1);
! 708: *sockfd = -1;
! 709: return -1;
! 710: }
! 711:
! 712: /* Measure time to make a connection and recalculate weights */
! 713: if (multihomed) {
! 714: deltatime = time(NULL) - deltatime;
! 715: HTTCPAddrWeights(host, deltatime);
! 716: }
! 717: free(p1);
! 718: return status;
! 719: }
! 720:
! 721:
! 722: /* HTDoAccept()
! 723: **
! 724: ** This function makes a non-blocking accept on a port and polls every
! 725: ** second until MAX_ACCEPT_POLL or interrupted by user.
! 726: **
! 727: ** BUGS Interrupted is not yet implemented!!!
! 728: **
! 729: ** Returns 0 if OK, -1 on error
! 730: */
! 731: PUBLIC int HTDoAccept ARGS2(HTRequest *, request, int, sockfd)
! 732: {
! 733: SockA soc_address; /* SockA is defined in tcp.h */
! 734: int status;
! 735: int cnt;
! 736: int soc_addrlen = sizeof(soc_address);
! 737: if (sockfd < 0) {
! 738: if (TRACE) fprintf(stderr, "HTDoAccept.. Bad socket number\n");
! 739: return -1;
! 740: }
! 741:
! 742: /* First make the socket non-blocking */
! 743: if((status = FCNTL(sockfd, F_GETFL, 0)) != -1) {
! 744: status |= FNDELAY;
! 745: status = FCNTL(sockfd, F_SETFL, status);
! 746: }
! 747: if (status == -1) {
! 748: HTErrorSysAdd(request, ERR_FATAL, NO, "fcntl");
! 749: return -1;
! 750: }
! 751:
! 752: /* Now poll every sekund */
! 753: for(cnt=0; cnt<MAX_ACCEPT_POLL; cnt++) {
! 754: if ((status = accept(sockfd, (struct sockaddr*) &soc_address,
! 755: &soc_addrlen)) >= 0) {
! 756: if (TRACE) fprintf(stderr,
! 757: "HTDoAccept.. Accepted new socket %d\n",
! 758: status);
! 759: return status;
! 760: } else
! 761: HTErrorSysAdd(request, ERR_WARNING, YES, "accept");
! 762: sleep(1);
! 763: }
! 764:
! 765: /* If nothing has happened */
! 766: if (TRACE)
! 767: fprintf(stderr, "HTDoAccept.. Timed out, no connection!\n");
! 768: HTErrorAdd(request, ERR_FATAL, NO, HTERR_TIME_OUT, NULL, 0, "HTDoAccept");
! 769: return -1;
1.1 timbl 770: }
771:
Webmaster