inet_gethost.c
来自「OTP是开放电信平台的简称」· C语言 代码 · 共 2,324 行 · 第 1/4 页
C
2,324 行
} else { fatal("Unexpected end of file on main input, errno = %d",errno); } } if (siz > *buff_size) { if (buff_size == 0) { *buff = ALLOC((*buff_size = siz)); } else { *buff = REALLOC(*buff, (*buff_size = siz)); } } if (read_exact(0,*buff, siz) != siz) { fatal("Unexpected end of file on main input, errno = %d",errno); } if (siz < 5) { fatal("Unexpected message on main input, message size %d less " "than minimum."); } return siz;}#endif /* !WIN32 */static OpType get_op(AddrByte *buff){ return (OpType) buff[4];}static AddrByte *get_op_addr(AddrByte *buff){ return buff + 4;}static SerialType get_serial(AddrByte *buff){ return get_int32(buff);}static ProtoType get_proto(AddrByte *buff){ return (ProtoType) buff[5];}static CtlType get_ctl(AddrByte *buff){ return (CtlType) buff[5];}static AddrByte *get_data(AddrByte *buff){ return buff + 6;}static int get_debug_level(AddrByte *buff){ return get_int32(buff + 6);}#ifdef WIN32static int send_mes_to_worker(QueItem *m, Worker *pw) { if (!enque_mesq(pw->writeto, m)) { warning("Unable to send to child process."); return -1; } return 0;}#elsestatic int send_request_to_worker(AddrByte *pr, int rsize, Worker *pw) { AddrByte hdr[PACKET_BYTES]; PUT_PACKET_BYTES(hdr, rsize); if (write_exact(pw->writeto, hdr, PACKET_BYTES) < 0) { warning("Unable to write to child process."); return -1; } if (write_exact(pw->writeto, (AddrByte *) pr, rsize) < 0) { warning("Unable to write to child process."); return -1; } return 0;}#endif /* !WIN32 */#ifdef WIN32static int relay_reply(Worker *pw){ QueItem *m; if (!deque_mesq(pw->readfrom,&m)) { return 0; } if (!enque_mesq(to_erlang,m)) { FREE(m); return 0; } return 1;}static int ignore_reply(Worker *pw) { QueItem *m; if (!deque_mesq(pw->readfrom,&m)) { return 0; } FREE(m); return 1;}#else/* Static buffers used by the next three functions */static AddrByte *relay_buff = NULL; static int relay_buff_size = 0;static int fillin_reply(Worker *pw){ int length; if (READ_PACKET_BYTES(pw->readfrom, &length) != PACKET_BYTES) { warning("Malformed reply (header) from worker process %d.", pw->pid); return -1; } if (relay_buff_size < (length + PACKET_BYTES)) { if (!relay_buff_size) { relay_buff = ALLOC((relay_buff_size = (length + PACKET_BYTES))); } else { relay_buff = REALLOC(relay_buff, (relay_buff_size = (length + PACKET_BYTES))); } } PUT_PACKET_BYTES(relay_buff, length); if (read_exact(pw->readfrom, relay_buff + PACKET_BYTES, length) != length) { warning("Malformed reply (data) from worker process %d.", pw->pid); return -1; } return length;}static int relay_reply(Worker *pw){ int length = fillin_reply(pw); /* Filled into the "global" buffer */ int res; if (length < 0) { return -1; } if ((res = write_exact(1, relay_buff, length + PACKET_BYTES)) < 0) { fatal("Cannot write reply to erlang process, errno = %d.", errno); } else if (res == 0) { DEBUGF(1,("Erlang has closed write pipe.")); return 0; } return length;}static int ignore_reply(Worker *pw){ return fillin_reply(pw);}#endif /* !WIN32 *//* * Domain name "parsing" and worker specific queing */static void domaincopy(AddrByte *out, AddrByte *in){ AddrByte *ptr = out; *ptr++ = *in++; *ptr++ = *in++; switch(*out) { case OP_GETHOSTBYNAME: while(*in != '\0' && *in != '.') ++in; strncpy((char*)ptr, (char*)in, DOMAINNAME_MAX-2); ptr[DOMAINNAME_MAX-3] = '\0'; DEBUGF(4,("Saved domainname %s.", ptr)); return; case OP_GETHOSTBYADDR: memcpy(ptr,in, ((out[1] == PROTO_IPV4) ? UNIT_IPV4 : UNIT_IPV6) - 1); DEBUGF(4, ("Saved domain address: %s.", format_address(((out[1] == PROTO_IPV4) ? UNIT_IPV4 : UNIT_IPV6) - 1,ptr))); return; default: fatal("Trying to copy buffer not containing valid domain, [%d,%d].", (int) out[0], (int) out[1]); }}static int domaineq(AddrByte *d1, AddrByte *d2){ if (d1[0] != d2[0] || d1[1] != d2[1]) { return 0; } switch (d1[0]) { case OP_GETHOSTBYNAME: return !strcmp((char*)d1+2,(char*)d2+2); case OP_GETHOSTBYADDR: return !memcmp(d1+2,d2+2, ((d1[1] == PROTO_IPV4) ? UNIT_IPV4 : UNIT_IPV6) - 1); default: fatal("Trying to compare buffers not containing valid domain, " "[%d,%d].", (int) d1[0], (int) d1[1]); return -1; /* Lint... */ }} static int get_domainname(AddrByte *inbuff, int insize, AddrByte *domainbuff){ OpType op = get_op(inbuff); ProtoType proto; int i; AddrByte *data; data = get_data(inbuff); switch (op) { case OP_GETHOSTBYNAME: data = get_data(inbuff); for (i = (data - inbuff); i < insize && inbuff[i] != '\0'; ++i) ; if (i < insize) { domaincopy(domainbuff, get_op_addr(inbuff)); return 0; } DEBUGF(3, ("Could not pick valid domainname in " "gethostbyname operation")); return -1; case OP_GETHOSTBYADDR: proto = get_proto(inbuff); i = insize - (data - inbuff); if ((proto == PROTO_IPV4 && i == UNIT_IPV4) || (proto == PROTO_IPV6 && i == UNIT_IPV6)) { /* An address buffer */ domaincopy(domainbuff, get_op_addr(inbuff)); return 0; } DEBUGF(3, ("Could not pick valid domainname in gethostbyaddr " "operation")); return -1; default: DEBUGF(2, ("Could not pick valid domainname because of " "invalid opcode %d.", (int) op)); return -1; }}/* * Worker subprocesses with utilities */#ifdef WIN32static int create_worker(Worker *pworker, int save_que){ MesQ **thread_data = ALLOC(2*sizeof(MesQ *)); DWORD tid; if (!create_mesq(thread_data)) { fatal("Could not create, pipes for subprocess, errno = %d", GetLastError()); } if (!create_mesq(thread_data + 1)) { fatal("Could not create, pipes for subprocess, errno = %d", GetLastError()); } /* Save those before the thread starts */ pworker->writeto = thread_data[0]; pworker->readfrom = thread_data[1]; if (((HANDLE) _beginthreadex(NULL, 0, worker_loop, thread_data, 0, &tid)) == NULL) { fatal("Could not create thread errno = %d", GetLastError()); } pworker->pid = tid; pworker->state = WORKER_FREE; pworker->serial = INVALID_SERIAL; if (!save_que) { pworker->que_first = pworker->que_last = NULL; pworker->que_size = 0; } DEBUGF(3,("Created worker[%ld] with fd %d", (long) pworker->pid, (int) pworker->readfrom)); return 0;}#elsestatic int create_worker(Worker *pworker, int save_que){ int p0[2], p1[2]; pid_t child; if (pipe(p0)) { warning("Could not create, pipes for subprocess, errno = %d", errno); return -1; } if (pipe(p1)) { warning("Could not create, pipes for subprocess, errno = %d", errno); close(p0[0]); close(p0[1]); return -1; } if ((child = fork()) < 0) { /* failure */ warning("Could not fork(), errno = %d", errno); close(p0[0]); close(p0[1]); close(p1[0]); close(p1[1]); return -1; } else if (child > 0) { /* parent */ close(p0[1]); close(p1[0]); pworker->writeto = p1[1]; pworker->readfrom = p0[0]; pworker->pid = child; pworker->state = WORKER_FREE; pworker->serial = INVALID_SERIAL; if (!save_que) { pworker->que_first = pworker->que_last = NULL; pworker->que_size = 0; } DEBUGF(3,("Created worker[%ld] with fd %d", (long) pworker->pid, (int) pworker->readfrom)); return 0; } else { /* child */ close(p1[1]); close(p0[0]); close_all_worker_fds(); /* Make "fatal" not find any children */ num_busy_workers = num_free_workers = num_stalled_workers = 0; if((dup2(p1[0],0) < 0) || (dup2(p0[1],1) < 0)) { fatal("Worker could not dup2(), errno = %d", errno); return -1; /* lint... */ } close(p1[0]); close(p0[1]); signal(SIGCHLD, SIG_IGN); return worker_loop(); }}static void close_all_worker_fds(void) { int w,i; Worker *workers[3] = {free_workers, busy_workers, stalled_workers}; int wsizes[3] = {num_free_workers, num_busy_workers, num_stalled_workers}; for (w = 0; w < 3; ++w) { for (i = 0; i < wsizes[w]; ++i) { if (workers[w][i].state != WORKER_EMPTY) { close(workers[w][i].readfrom); close(workers[w][i].writeto); } } }}#endif /* !WIN32 */#ifdef WIN32DWORD WINAPI worker_loop(void *v)#elsestatic int worker_loop(void)#endif{ struct hostent *he; AddrByte *req = NULL; size_t req_size = 0; int this_size; AddrByte *reply = NULL; size_t reply_size = 0; size_t data_size; int error_num; SerialType serial; OpType op; ProtoType proto; AddrByte *data; int free_he;#ifdef WIN32 QueItem *m = NULL; MesQ *readfrom = ((MesQ **) v)[0]; MesQ *writeto = ((MesQ **) v)[1]; FREE(v);#endif for(;;) {#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... */ free_he = 0; switch (op) { case OP_GETHOSTBYNAME: if (proto != PROTO_IPV4) {#if defined(HAVE_GETIPNODEBYNAME) && !defined(WIN32) /* IP V6 support */ if (proto == PROTO_IPV6) { he = getipnodebyname(data, AF_INET6, AI_DEFAULT, &error_num); free_he = 1; error_num = map_netdb_error(error_num); } else { /* Not supported... */ he = NULL; error_num = ERRCODE_NOTSUP; } #else /* Not supported... */ he = NULL; error_num = ERRCODE_NOTSUP;#endif } else { DEBUGF(4,("Starting gethostbyname(%s)",data)); he = gethostbyname((char*)data); error_num = he ? 0 : map_netdb_error(h_errno); if (error_num) { DEBUGF(4,("gethostbyname(%s) gave error: %d", data, error_num)); } else { DEBUGF(4,("gethostbyname(%s) gave success", data)); } } if (!he) { data_size = build_error_reply(serial, error_num, &reply, &reply_size); } else { data_size = build_reply(serial, he, &reply, &reply_size);#if defined(HAVE_GETIPNODEBYNAME) && !defined(WIN32) /* IP V6 support */ if (free_he) { freehostent(he); }#endif } break; case OP_GETHOSTBYADDR: if (proto != PROTO_IPV4) {#if defined(HAVE_GETIPNODEBYADDR) && !defined(WIN32) /* IP V6 support */ if (proto == PROTO_IPV6) { struct in6_addr ia; memcpy(ia.s6_addr, data, 16); he = getipnodebyaddr(&ia, 16, AF_INET6, &error_num); free_he = 1; error_num = map_netdb_error(error_num); } else { /* Not supported... */ he = NULL; error_num = ERRCODE_NOTSUP; } #else /* Not supported... */ he = NULL; error_num = ERRCODE_NOTSUP;#endif } else { struct in_addr ia; memcpy(&ia.s_addr, data, 4); /* Alignment required... */ he = gethostbyaddr((const char *) &ia, 4, AF_INET); error_num = map_netdb_error(h_errno); } if (!he) { data_size = build_error_reply(serial, error_num, &reply, &reply_size); } else { data_size = build_reply(serial, he, &reply, &reply_size);#if defined(HAVE_GETIPNODEBYADDR) && !defined(WIN32) /* IP V6 support */ if (free_he) { freehostent(he); }#endif } break; default: data_size = build_error_reply(serial, ERRCODE_NOTSUP, &reply, &reply_size); break; }#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 write(1, reply, data_size); /* No signals expected */#endif }#ifdef WIN32 fail: if (m != NULL) { FREE(m); } close_mesq(readfrom); close_mesq(writeto); if (reply) { FREE(reply); } return 1;#endif}static int map_netdb_error(int netdb_code){ switch (netdb_code) {#ifdef HOST_NOT_FOUND case HOST_NOT_FOUND: return ERRCODE_HOST_NOT_FOUND;#endif#ifdef TRY_AGAIN case TRY_AGAIN: return ERRCODE_TRY_AGAIN;#endif#ifdef NO_RECOVERY case NO_RECOVERY: return ERRCODE_NO_RECOVERY;#endif#if defined(NO_DATA) || defined(NO_ADDRESS)#ifdef NO_DATA case NO_DATA:#endif#ifdef NO_ADDRESS#if !defined(NO_DATA) || (NO_DATA != NO_ADDRESS)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?