DWORD WINAPI worker_loop()

in erts/etc/common/inet_gethost.c [1665:1964]


DWORD WINAPI worker_loop(void *v)
#else
static int worker_loop(void)
#endif
{
    AddrByte *req = NULL;
    size_t req_size = 0;
    int this_size;
    AddrByte *reply = NULL;
    size_t reply_size = 0;
    size_t data_size;

#ifdef WIN32
    QueItem *m = NULL;
    MesQ *readfrom = ((MesQ **) v)[0];
    MesQ *writeto = ((MesQ **) v)[1];
    /* XXX:PaN */
    FREE(v);
#endif

    for(;;) {
#ifdef HAVE_GETADDRINFO
	struct addrinfo *ai = NULL;
#endif
	struct hostent *he = NULL;
#ifdef HAVE_GETNAMEINFO
	struct sockaddr *sa = NULL;
	char name[NI_MAXHOST];
#endif
#if defined(HAVE_GETIPNODEBYNAME) || defined(HAVE_GETIPNODEBYADDR)
	int free_he = 0;
#endif
	int error_num = 0;
	SerialType serial;
	OpType op;
	ProtoType proto;
	AddrByte *data;

#ifdef WIN32
	WaitForSingleObject(event_mesq(readfrom),INFINITE);
	DEBUGF(4,("Worker got data on message que."));

	if(!deque_mesq(readfrom,&m)) {
	    goto fail;
	}
	this_size = m->req_size;
	req = m->request;
#else	
	if (READ_PACKET_BYTES(0,&this_size) != PACKET_BYTES) {
	    DEBUGF(2,("Worker got error/EOF while reading size, exiting."));
	    exit(0);
	}
	if (this_size > req_size) {
	    if (req == NULL) {
		req = ALLOC((req_size = this_size));
	    } else {
		req = REALLOC(req, (req_size = this_size));
	    }
	}
	if (read_exact(0, req, (size_t) this_size) != this_size) {
	    DEBUGF(1,("Worker got EOF while reading data, exiting."));
	    exit(0);
	}
#endif
	/* Decode the request... */
	serial = get_serial(req);
	if (OP_CONTROL == (op = get_op(req))) {
	    CtlType ctl;
	    if (serial != INVALID_SERIAL) {
		DEBUGF(1, ("Worker got invalid serial: %d.", serial));
		exit(0);
	    }
	    switch (ctl = get_ctl(req)) {
	    case SETOPT_DEBUG_LEVEL:
		debug_level = get_debug_level(req);
		DEBUGF(debug_level, 
		       ("Worker debug_level = %d.", debug_level));
		break;
	    }
	    continue;
	}
	proto = get_proto(req);
	data = get_data(req);
	DEBUGF(4,("Worker got request, op = %d, proto = %d, data = %s.",
		  op,proto,data));
	/* Got a request, lets go... */
	switch (op) {
	case OP_GETHOSTBYNAME:
	    switch (proto) {
		
#ifdef HAVE_IN6
	    case PROTO_IPV6: { /* switch (proto) { */
#ifdef HAVE_GETADDRINFO
		struct addrinfo hints;
		
		memset(&hints, 0, sizeof(hints));
		hints.ai_flags = AI_CANONNAME;
		hints.ai_socktype = SOCK_STREAM;
		hints.ai_family = AF_INET6;
		DEBUGF(5, ("Starting getaddrinfo(%s, ...)", data));
		error_num = getaddrinfo((char *)data, NULL, &hints, &ai);
		DEBUGF(5,("getaddrinfo returned %d", error_num));
		if (error_num) {
		    error_num = map_netdb_error_ai(error_num);
		}
#elif defined(HAVE_GETIPNODEBYNAME) /*#ifdef HAVE_GETADDRINFO */
		DEBUGF(5,("Starting getipnodebyname(%s)",data));
		he = getipnodebyname(data, AF_INET6, 0, &error_num);
		if (he) {
		    free_he = 1;
		    error_num = 0;
		    DEBUGF(5,("getipnodebyname(,AF_INET6,,) OK"));
		} else {
		    DEBUGF(5,("getipnodebyname(,AF_INET6,,) error %d", error_num));
		    error_num = map_netdb_error(error_num);
		}
#elif defined(HAVE_GETHOSTBYNAME2) /*#ifdef HAVE_GETADDRINFO */
		DEBUGF(5,("Starting gethostbyname2(%s, AF_INET6)",data));
		he = gethostbyname2((char*)data, AF_INET6);
		if (he) {
		    error_num = 0;
		    DEBUGF(5,("gethostbyname2(, AF_INET6) OK"));
		} else {
		    error_num = map_netdb_error(h_errno);
		    DEBUGF(5,("gethostbyname2(, AF_INET6) error %d", h_errno));
		}
#else
		error_num = ERRCODE_NOTSUP;
#endif /*#ifdef HAVE_GETADDRINFO */
	    } break;
#endif /*ifdef HAVE_IN6 */
	    
	    case PROTO_IPV4: { /* switch (proto) { */
		DEBUGF(5,("Starting gethostbyname(%s)",data));
		he = gethostbyname((char*)data);
		if (he) {
		    error_num = 0;
		    DEBUGF(5,("gethostbyname OK"));
		} else {
		    error_num = map_netdb_error(h_errno);
		    DEBUGF(5,("gethostbyname error %d", h_errno));
		}
	    } break;
	    
	    default: /* switch (proto) { */
		/* Not supported... */
		error_num = ERRCODE_NOTSUP;
		break;
	    } /* switch (proto) { */
	    
	    if (he) {
		data_size = build_reply(serial, he, &reply, &reply_size);
#ifdef HAVE_GETIPNODEBYNAME
		if (free_he) {
		    freehostent(he);
		}
#endif
#ifdef HAVE_GETADDRINFO
	    } else if (ai) {
		data_size = build_reply_ai(serial, 16, ai,
					   &reply, &reply_size);
		freeaddrinfo(ai);
#endif
	    } else {
		data_size = build_error_reply(serial, error_num, 
					      &reply, &reply_size);
	    }
	    break; /* case OP_GETHOSTBYNAME: */

	case OP_GETHOSTBYADDR: /* switch (op) { */
	    switch (proto) {
#ifdef HAVE_IN6
	    case PROTO_IPV6: {
#ifdef HAVE_GETNAMEINFO
		struct sockaddr_in6 *sin;
		socklen_t salen = sizeof(*sin);
		
		sin = ALLOC(salen);
#ifndef NO_SA_LEN
		sin->sin6_len = salen;
#endif
		sin->sin6_family = AF_INET6;
		sin->sin6_port = 0;
		memcpy(&sin->sin6_addr, data, 16);
		sa = (struct sockaddr *)sin;
		DEBUGF(5,("Starting getnameinfo(,,%s,16,,,)",
			  format_address(16, data)));
		error_num = getnameinfo(sa, salen, name, sizeof(name),
					NULL, 0, NI_NAMEREQD);
		DEBUGF(5,("getnameinfo returned %d", error_num));
		if (error_num) {
		    error_num = map_netdb_error_ai(error_num);
		    sa = NULL;
		}
#elif defined(HAVE_GETIPNODEBYADDR) /*#ifdef HAVE_GETNAMEINFO*/
		struct in6_addr ia;
		memcpy(ia.s6_addr, data, 16);
		DEBUGF(5,("Starting getipnodebyaddr(%s,16,AF_INET6,)",
			  format_address(16, data)));
		he = getipnodebyaddr(&ia, 16, AF_INET6, &error_num);
		free_he = 1;
		if (! he) {
		    DEBUGF(5,("getipnodebyaddr error %d", error_num));
		    error_num = map_netdb_error(error_num);
		} else {
		    DEBUGF(5,("getipnodebyaddr OK"));
		}
#else /*#ifdef HAVE_GETNAMEINFO*/
		struct in6_addr ia;
		memcpy(ia.s6_addr, data, 16);
		DEBUGF(5,("Starting gethostbyaddr(%s,16,AF_INET6)",
			  format_address(16, data)));
		he = gethostbyaddr((const char *) &ia, 16, AF_INET6);
		if (! he) {
		    error_num = map_netdb_error(h_errno);
		    DEBUGF(5,("gethostbyaddr error %d", h_errno));
		} else {
		    DEBUGF(5,("gethostbyaddr OK"));
		}
#endif /* #ifdef HAVE_GETNAMEINFO */
	    } break; /* case PROTO_IPV6: { */
#endif /* #ifdef HAVE_IN6 */
			    
	    case PROTO_IPV4: { /* switch(proto) { */
		struct in_addr ia;
		memcpy(&ia.s_addr, data, 4); /* Alignment required... */
		DEBUGF(5,("Starting gethostbyaddr(%s,4,AF_INET)",
			  format_address(4, data)));
		he = gethostbyaddr((const char *) &ia, 4, AF_INET);
		if (! he) {
		    error_num = map_netdb_error(h_errno);
		    DEBUGF(5,("gethostbyaddr error %d", h_errno));
		} else {
		    DEBUGF(5,("gethostbyaddr OK"));
		}
	    } break;
	    
	    default:
		error_num = ERRCODE_NOTSUP;
	    } /* switch(proto) { */
	    
	    if (he) {
		data_size = build_reply(serial, he, &reply, &reply_size);
#ifdef HAVE_GETIPNODEBYADDR
		if (free_he) {
		    freehostent(he);
		}
#endif
#ifdef HAVE_GETNAMEINFO
	    } else if (sa) {
		struct addrinfo res;
		memset(&res, 0, sizeof(res));
		res.ai_canonname = name;
		res.ai_addr = sa;
		res.ai_next = NULL;
		data_size = build_reply_ai(serial, 16, &res,
					   &reply, &reply_size);
		free(sa);
#endif
	    } else {
		data_size = build_error_reply(serial, error_num, 
					      &reply, &reply_size);
	    }
	    break; /* case OP_GETHOSTBYADR: */

	default:
	    data_size = build_error_reply(serial, ERRCODE_NOTSUP, 
					  &reply, &reply_size);
	    break;
	} /* switch (op) { */

#ifdef WIN32
	m = REALLOC(m, sizeof(QueItem) - 1 + data_size - PACKET_BYTES);
	m->next = NULL;
	m->req_size = data_size - PACKET_BYTES;
	memcpy(m->request,reply + PACKET_BYTES,data_size - PACKET_BYTES);
	if (!enque_mesq(writeto,m)) {
	    goto fail;
	}
	m = NULL;
#else
	/* expect no signals */
	if (write(1, reply, data_size) < 0)
	    goto fail;
#endif
    } /* for (;;) */

 fail:
#ifdef WIN32
    if (m != NULL) {
	FREE(m);
    }
    close_mesq(readfrom);
    close_mesq(writeto);
    if (reply) {
	FREE(reply);
    }
#endif
    return 1;
}