📄 event.c
字号:
/* * We had previously received a reply, so we don't need * to do anything here. */ if (request->proxy_reply) { if (memcmp(request->proxy_reply->vector, packet->vector, sizeof(request->proxy_reply->vector)) == 0) { DEBUG2("Discarding duplicate reply from home server %s port %d - ID: %d for request %d", inet_ntop(packet->src_ipaddr.af, &packet->src_ipaddr.ipaddr, buffer, sizeof(buffer)), packet->src_port, packet->id, request->number); } else { /* * ? The home server gave us a new proxy * reply, which doesn't match the old * one. Delete it. */ DEBUG2("Ignoring conflicting proxy reply"); } /* assert that there's an event queued for request? */ rad_free(&packet); return NULL; } switch (request->child_state) { case REQUEST_QUEUED: case REQUEST_RUNNING: rad_panic("Internal sanity check failed for child state"); break; case REQUEST_REJECT_DELAY: case REQUEST_CLEANUP_DELAY: case REQUEST_DONE: radlog(L_ERR, "Reply from home server %s port %d - ID: %d arrived too late for request %d. Try increasing 'retry_delay' or 'max_request_time'", inet_ntop(packet->src_ipaddr.af, &packet->src_ipaddr.ipaddr, buffer, sizeof(buffer)), packet->src_port, packet->id, request->number); /* assert that there's an event queued for request? */ rad_free(&packet); return NULL; case REQUEST_PROXIED: break; } request->proxy_reply = packet;#if 0 /* * Perform RTT calculations, as per RFC 2988 (for TCP). * Note that we do so only if we sent one request, and * received one response. If we sent two requests, we * have no idea if the response is for the first, or for * the second request/ */ if (request->num_proxied_requests == 1) { int rtt; home_server *home = request->home_server; rtt = now.tv_sec - request->proxy_when.tv_sec; rtt *= USEC; rtt += now.tv_usec; rtt -= request->proxy_when.tv_usec; if (!home->has_rtt) { home->has_rtt = TRUE; home->srtt = rtt; home->rttvar = rtt / 2; } else { home->rttvar -= home->rttvar >> 2; home->rttvar += (home->srtt - rtt); home->srtt -= home->srtt >> 3; home->srtt += rtt >> 3; } home->rto = home->srtt; if (home->rttvar > (USEC / 4)) { home->rto += home->rttvar * 4; } else { home->rto += USEC; } }#endif /* * There's no incoming request, so it's a proxied packet * we originated. */ if (!request->packet) { received_response_to_ping(request); return NULL; } request->child_state = REQUEST_QUEUED; request->when = now; request->delay = USEC; request->priority = RAD_LISTEN_PROXY; tv_add(&request->when, request->delay); /* * Wait a bit will take care of max_request_time */ INSERT_EVENT(wait_a_bit, request); return request;}static void event_detail_timer(void *ctx){ rad_listen_t *listener = ctx; RAD_REQUEST_FUNP fun; REQUEST *request; if (listener->recv(listener, &fun, &request)) { if (!thread_pool_addrequest(request, fun)) { request->child_state = REQUEST_DONE; } }}static void handle_signal_self(int flag){ if ((flag & (RADIUS_SIGNAL_SELF_EXIT | RADIUS_SIGNAL_SELF_TERM)) != 0) { if ((flag & RADIUS_SIGNAL_SELF_EXIT) != 0) { fr_event_loop_exit(el, 1); } else { fr_event_loop_exit(el, 2); } return; } /* else exit/term flags weren't set */ /* * Tell the even loop to stop processing. */ if ((flag & RADIUS_SIGNAL_SELF_HUP) != 0) { time_t when; static time_t last_hup = 0; DEBUG("Received HUP signal."); when = time(NULL); if ((int) (when - last_hup) < 5) { radlog(L_INFO, "Ignoring HUP (less than 5s since last one)"); return; } last_hup = when; fr_event_loop_exit(el, 0x80); } if ((flag & RADIUS_SIGNAL_SELF_DETAIL) != 0) { rad_listen_t *this; for (this = mainconfig.listen; this != NULL; this = this->next) { int delay; struct timeval when; if (this->type != RAD_LISTEN_DETAIL) continue; delay = detail_delay(this); if (!delay) continue; fr_event_now(el, &now); when = now; tv_add(&when, delay); if (delay > 100000) { DEBUG2("Delaying next detail event for %d.%01u seconds.", delay / USEC, (delay % USEC) / 100000); } if (!fr_event_insert(el, event_detail_timer, this, &when, NULL)) { radlog(L_ERR, "Failed remembering timer"); exit(1); } } } if ((flag & RADIUS_SIGNAL_SELF_NEW_FD) != 0) { rad_listen_t *this; for (this = mainconfig.listen; this != NULL; this = this->next) { if (this->type != RAD_LISTEN_PROXY) continue; if (!fr_event_fd_insert(el, 0, this->fd, event_socket_handler, this)) { radlog(L_ERR, "Failed remembering handle for proxy socket!"); exit(1); } } }}#ifdef __MINGW32__void radius_signal_self(int flag){ handle_signal_self(flag);}#else/* * Inform ourselves that we received a signal. */void radius_signal_self(int flag){ ssize_t rcode; uint8_t buffer[16]; /* * The read MUST be non-blocking for this to work. */ rcode = read(self_pipe[0], buffer, sizeof(buffer)); if (rcode > 0) { ssize_t i; for (i = 0; i < rcode; i++) { buffer[0] |= buffer[i]; } } else { buffer[0] = 0; } buffer[0] |= flag; write(self_pipe[1], buffer, 1);}static void event_signal_handler(UNUSED fr_event_list_t *xel, UNUSED int fd, UNUSED void *ctx){ ssize_t i, rcode; uint8_t buffer[32]; rcode = read(self_pipe[0], buffer, sizeof(buffer)); if (rcode <= 0) return; /* * Merge pending signals. */ for (i = 0; i < rcode; i++) { buffer[0] |= buffer[i]; } handle_signal_self(buffer[0]);}#endifstatic void event_socket_handler(fr_event_list_t *xel, UNUSED int fd, void *ctx){ rad_listen_t *listener = ctx; RAD_REQUEST_FUNP fun; REQUEST *request; rad_assert(xel == el); xel = xel; if (listener->fd < 0) rad_panic("Socket was closed on us!"); if (!listener->recv(listener, &fun, &request)) return; if (!thread_pool_addrequest(request, fun)) { request->child_state = REQUEST_DONE; }}/* * This function is called periodically to see if any FD's are * available for reading. */static void event_poll_fds(UNUSED void *ctx){ int rcode; RAD_REQUEST_FUNP fun; REQUEST *request; rad_listen_t *this; struct timeval when; fr_event_now(el, &now); when = now; when.tv_sec += 1; for (this = mainconfig.listen; this != NULL; this = this->next) { if (this->fd >= 0) continue; /* * Try to read something. * * FIXME: This does poll AND receive. */ rcode = this->recv(this, &fun, &request); if (!rcode) continue; rad_assert(fun != NULL); rad_assert(request != NULL); if (!thread_pool_addrequest(request, fun)) { request->child_state = REQUEST_DONE; } /* * We have an FD. Start watching it. */ if (this->fd >= 0) { /* * ... unless it's a detail file. In * that case, we rely on the signal to * self to know when to continue * processing the detail file. */ if (this->type == RAD_LISTEN_DETAIL) continue; /* * FIXME: this should be SNMP handler, * and we should do SOMETHING when the * fd is closed! */ if (!fr_event_fd_insert(el, 0, this->fd, event_socket_handler, this)) { char buffer[256]; this->print(this, buffer, sizeof(buffer)); rad_panic("Failed creating handler for snmp"); } } } /* * Reset the poll. */ if (!fr_event_insert(el, event_poll_fds, NULL, &when, NULL)) { radlog(L_ERR, "Failed creating handler"); exit(1); }}static void event_status(struct timeval *wake){#if !defined(HAVE_PTHREAD_H) && defined(WNOHANG) int argval;#endif if (debug_flag == 0) { if (just_started) { radlog(L_INFO, "Ready to process requests."); just_started = FALSE; } return; } if (!wake) { DEBUG("Ready to process requests."); } else if ((wake->tv_sec != 0) || (wake->tv_usec >= 100000)) { DEBUG("Waking up in %d.%01u seconds.", (int) wake->tv_sec, (unsigned int) wake->tv_usec / 100000); } /* * FIXME: Put this somewhere else, where it isn't called * all of the time... */#if !defined(HAVE_PTHREAD_H) && defined(WNOHANG) /* * If there are no child threads, then there may * be child processes. In that case, wait for * their exit status, and throw that exit status * away. This helps get rid of zxombie children. */ while (waitpid(-1, &argval, WNOHANG) > 0) { /* do nothing */ }#endif}/* * Externally-visibly functions. */int radius_event_init(CONF_SECTION *cs, int spawn_flag){ int i; int has_snmp_listener = FALSE; rad_listen_t *this, *head = NULL; if (el) return 0; time(&start_time); el = fr_event_list_create(event_status); if (!el) return 0; pl = fr_packet_list_create(0); if (!el) return 0; request_num_counter = 0; /* * Move all of the thread calls to this file? * * It may be best for the mutexes to be in this file... */ have_children = spawn_flag; if (mainconfig.proxy_requests) { /* * Create the tree for managing proxied requests and * responses. */ proxy_list = fr_packet_list_create(1); if (!proxy_list) return 0;#ifdef HAVE_PTHREAD_H if (pthread_mutex_init(&proxy_mutex, NULL) != 0) { radlog(L_ERR, "FATAL: Failed to initialize proxy mutex: %s", strerror(errno)); exit(1); }#endif } /* * Just before we spawn the child threads, force the log * subsystem to re-open the log file for every write. */ if (spawn_flag) force_log_reopen();#ifdef HAVE_PTHREAD_H if (thread_pool_init(cs, spawn_flag) < 0) { exit(1); }#endif if (check_config) { DEBUG2("%s: #### Skipping IP addresses and Ports ####", mainconfig.name); return 1; }#ifndef __MINGW32__ /* * Child threads need a pipe to signal us, as do the * signal handlers. */ if (pipe(self_pipe) < 0) { radlog(L_ERR, "radiusd: Error opening internal pipe: %s", strerror(errno)); exit(1); } if (fcntl(self_pipe[0], F_SETFL, O_NONBLOCK | FD_CLOEXEC) < 0) { radlog(L_ERR, "radiusd: Error setting internal flags: %s", strerror(errno)); exit(1); } if (fcntl(self_pipe[1], F_SETFL, O_NONBLOCK | FD_CLOEXEC) < 0) { radlog(L_ERR, "radiusd: Error setting internal flags: %s", strerror(errno)); exit(1); } if (!fr_event_fd_insert(el, 0, self_pipe[0], event_signal_handler, el)) { radlog(L_ERR, "Failed creating handler for signals"); exit(1); }#endif /* * Mark the proxy Fd's as unused. */ for (i = 0; i < 32; i++) proxy_fds[i] = -1; DEBUG2("%s: #### Opening IP addresses and Ports ####", mainconfig.name); if (listen_init(cs, &head) < 0) { _exit(1); } /* * Add all of the sockets to the event loop. */ for (this = head; this != NULL; this = this->next) { char buffer[256]; this->print(this, buffer, sizeof(buffer)); switch (this->type) { case RAD_LISTEN_DETAIL: DEBUG("Listening on %s", buffer); has_detail_listener = TRUE; break; case
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -