handler_t network_server_handle_fdevent(void *s, void *context, int revents) { server *srv = (server *)s; server_socket *srv_socket = (server_socket *)context; connection *con; int loops = 0; UNUSED(context); if (revents != FDEVENT_IN) { log_error_write(srv, __FILE__, __LINE__, "sdd", "strange event for server socket", srv_socket->fd, revents); return HANDLER_ERROR; } /* accept()s at most 100 connections directly * * we jump out after 100 to give the waiting connections a chance */ for (loops = 0; loops < 100 && NULL != (con = connection_accept(srv, srv_socket)); loops++) { handler_t r; connection_state_machine(srv, con); switch(r = plugins_call_handle_joblist(srv, con)) { case HANDLER_FINISHED: case HANDLER_GO_ON: break; default: log_error_write(srv, __FILE__, __LINE__, "d", r); break; } } return HANDLER_GO_ON; }
static handler_t network_server_handle_fdevent(server *srv, void *context, int revents) { server_socket *srv_socket = (server_socket *)context; connection *con; int loops = 0; UNUSED(context); if (0 == (revents & FDEVENT_IN)) { log_error_write(srv, __FILE__, __LINE__, "sdd", "strange event for server socket", srv_socket->fd, revents); return HANDLER_ERROR; } /* accept()s at most 100 connections directly * * we jump out after 100 to give the waiting connections a chance */ for (loops = 0; loops < 100 && NULL != (con = connection_accept(srv, srv_socket)); loops++) { connection_state_machine(srv, con); } return HANDLER_GO_ON; }
//处理监听套接字的可读(register时指定用该函数) handler_t network_server_handle_fdevent(void *s, void *context, int revents) { server *srv = (server *)s; server_socket *srv_socket = (server_socket *)context; connection *con; int loops = 0; UNUSED(context); /* 首先要判断传入的event事件是否是FDEVENT_IN,也就是说,只可能在fd有可读数据的时候才触发该函数,其他的情况都错误。 */ if (revents != FDEVENT_IN) { log_error_write(srv, __FILE__, __LINE__, "sdd", "strange event for server socket", srv_socket->fd, revents); return HANDLER_ERROR; } /* 接收客户端连接请求,每个监听套接口描述符一次接收请求数目最大为100,使得各监听套接口上的连接请求都得到及时处理。 */ //connection_accept()函数用来完成连接套接口描述符的创建 for (loops = 0; loops < 100 && NULL != (con=connection_accept(srv, srv_socket)); loops++) { handler_t r; //connection_state_machine()函数(连接状态转换管理器)和plugins_call_handle_joblist()函数用于对请求连接进行处理。 connection_state_machine(srv, con); switch(r = plugins_call_handle_joblist(srv, con)) { case HANDLER_FINISHED: case HANDLER_GO_ON: break; default: log_error_write(srv, __FILE__, __LINE__, "d", r); break; } } return HANDLER_GO_ON; }
int main(void) { int server; video_init(); wifi_init(); while (!wifi_connect()); server = wifi_listen(); while (1) { static Connection conn; int i; uint32 data_goal; connection_accept(&conn, server); conn.card_type = cardmeGetType(); iprintf("Card type %d\n", conn.card_type); if (conn.card_type <= 0) { close(conn.fd); continue; } conn.card_size = cardmeSize(conn.card_type); iprintf("%d byte EEPROM\n", conn.card_size); for (conn.address = 0; conn.address < conn.card_size; conn.address += sizeof conn.buffer) { int sent = 0; cardmeReadEeprom(conn.address, conn.buffer, sizeof conn.buffer, conn.card_type); data_goal = Wifi_GetStats(WSTAT_TXDATABYTES) + sizeof conn.buffer; do { sent += send(conn.fd, conn.buffer + sent, sizeof conn.buffer - sent, 0); } while (sent < sizeof conn.buffer); /* * dswifi's TCP stack is buggy... or sometihing. It's retransmitting every packet * several times. This seems to help a little. Also, this should help work around * the fact that dswifi doesn't flush any buffers on close(). */ while (Wifi_GetStats(WSTAT_TXDATABYTES) < data_goal) { swiWaitForVBlank(); } iprintf("(%d bytes)\x1b[60D", conn.address); } iprintf("Complete. \n"); /* * Wait for the other end to close the connection. * Closing it immediately seems to just lose data in * dswifi's buffers... */ while (recv(conn.fd, conn.buffer, sizeof conn.buffer, 0) > 0); close(conn.fd); } return 0; }
int main(int argc, char *argv[]) { time_t t; struct tm *tm; fd_set master; fd_set read_fds; int fdmax, i, j=0, k=0; int sockfd=0; char *cad = malloc(BUFSIZE); struct sockaddr_in my_addr, client_addr; bind_textdomain_codeset ("fuentes", "UTF-8"); setlocale(LC_ALL, ""); bindtextdomain("fuentes", "idioma"); textdomain("fuentes"); if(argc==2) { CONEXIONES clientes[MAX_CONN]; FD_ZERO(&master); FD_ZERO(&read_fds); connect_request(&sockfd, &my_addr, atoi(argv[1])); FD_SET(sockfd, &master); t = time(NULL); tm=localtime(&t); fdmax = sockfd; while(1){ read_fds = master; if(select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1){ perror(_("Seleccionar")); exit(4); } for (i = 0; i <= fdmax; i++){ if (FD_ISSET(i, &read_fds)){ if (i == sockfd) { clientes[j].fds=connection_accept(&master, &fdmax, sockfd, &client_addr); clientes[j].dir = client_addr.sin_addr; clientes[j].hora = tm->tm_hour; clientes[j].min = tm->tm_min; clientes[j].seg = tm->tm_sec; j++; } else { for(k=0;k<j;k++) { if(clientes[k].fds == i) { sprintf(cad, "[%s]-Dice: ",inet_ntoa(clientes[k].dir)); send_recv(i, &master, sockfd, fdmax, cad); } } } } } } return 0; } else { printf(_("Número de argumentos invalido\n")); return -1; } }
void server_wait(server *s) { int maxfd = s->socket; fd_set rfds; FD_ZERO(&rfds); FD_SET(s->socket, &rfds); GList *i; for (i = s->connections; i != NULL; i = i->next) { connection *c = (connection *)i->data; int fd = connection_socket(c); if (fd > maxfd) maxfd = fd; FD_SET(fd, &rfds); } struct timeval tv; tv.tv_sec = TIMEOUT_SEC; tv.tv_usec = TIMEOUT_USEC; int status = select(maxfd + 1, &rfds, NULL, NULL, &tv); if (status > 0) { if (FD_ISSET(s->socket, &rfds)) { if (!g_queue_is_empty(s->free_connections)) { connection *c = (connection *)g_queue_pop_head(s->free_connections); s->connections = g_list_append(s->connections, c); connection_accept(c, s->socket); if (connection_socket(c) == 0) halt_error("Socket accept really shouldn't fail"); } } GList *j = s->connections; while (j != NULL) { GList *next = j->next; connection *c = (connection *)j->data; if (FD_ISSET(connection_socket(c), &rfds)) { if (connection_receive(c)) { j->data = NULL; s->connections = g_list_delete_link(s->connections, j); g_queue_push_tail(s->free_connections, c); } } j = next; } } else if (status == 0) { // connection timeout GList *j = s->connections; while (j != NULL) { GList *next = j->next; connection *c = (connection *)j->data; connection_timeout_increment(c, TIMEOUT_SEC + (((float)TIMEOUT_USEC) / 1000000.0f)); if (connection_timedout(c)) { j->data = NULL; s->connections = g_list_delete_link(s->connections, j); g_queue_push_tail(s->free_connections, c); } j = next; } } else { // TODO: Don't know if this is ever a fatal error //halt_error("Error in socket select"); return; } }
int main(int argc, char **argv) { int opt; char *user =0; char *host; unsigned long port; int pid; int s; int conn; int delim; progname =*argv; phccmax =0; #ifdef SSLSVD while ((opt =getopt(argc, (const char **)argv, "c:C:i:x:u:l:Eb:hpt:vVU:/:Z:K:")) != opteof) { #else while ((opt =getopt(argc, (const char **)argv, "c:C:i:x:u:l:Eb:hpt:vV")) != opteof) { #endif switch(opt) { case 'c': scan_ulong(optarg, &cmax); if (cmax < 1) usage(); break; case 'C': delim =scan_ulong(optarg, &phccmax); if (phccmax < 1) usage(); if (optarg[delim] == ':') { if (ipsvd_fmt_msg(&msg, optarg +delim +1) == -1) die_nomem(); if (! stralloc_0(&msg)) die_nomem(); phccmsg =msg.s; } break; case 'i': if (instructs) usage(); instructs =optarg; break; case 'x': if (instructs) usage(); instructs =optarg; iscdb =1; break; case 'u': user =(char*)optarg; break; case 'l': if (! stralloc_copys(&local_hostname, optarg)) die_nomem(); if (! stralloc_0(&local_hostname)) die_nomem(); break; case 'E': ucspi =0; break; case 'b': scan_ulong(optarg, &backlog); break; case 'h': lookuphost =1; break; case 'p': lookuphost =1; paranoid =1; break; case 't': scan_ulong(optarg, &timeout); break; case 'v': ++verbose; break; #ifdef SSLSVD case 'U': ssluser =(char*)optarg; break; case '/': root =(char*)optarg; break; case 'Z': cert =(char*)optarg; break; case 'K': key =(char*)optarg; break; #endif case 'V': strerr_warn1(VERSION, 0); case '?': usage(); } } argv +=optind; if (! argv || ! *argv) usage(); host =*argv++; if (! argv || ! *argv) usage(); local_port =*argv++; if (! argv || ! *argv) usage(); prog =(const char **)argv; if (phccmax > cmax) phccmax =cmax; if (user) if (! uidgids_get(&ugid, user)) { if (errno) strerr_die4sys(111, FATAL, "unable to get user/group: ", user, ": "); strerr_die3x(100, FATAL, "unknown user/group: ", user); } #ifdef SSLSVD svuser =user; client =0; if ((getuid() == 0) && (! ssluser)) strerr_die2x(100, FATAL, "-U ssluser must be set when running as root"); if (ssluser) if (! uidgids_get(&sslugid, ssluser)) { if (errno) strerr_die4sys(111, FATAL, "unable to get user/group: ", ssluser, ": "); strerr_die3x(100, FATAL, "unknown user/group: ", ssluser); } if (! cert) cert ="./cert.pem"; if (! key) key =cert; if (matrixSslOpen() < 0) fatal("unable to initialize ssl"); if (matrixSslReadKeys(&keys, cert, key, 0, ca) < 0) { if (client) fatal("unable to read cert, key, or ca file"); fatal("unable to read cert or key file"); } if (matrixSslNewSession(&ssl, keys, 0, SSL_FLAGS_SERVER) < 0) strerr_die2x(111, FATAL, "unable to create ssl session"); #endif dns_random_init(seed); sig_block(sig_child); sig_catch(sig_child, sig_child_handler); sig_catch(sig_term, sig_term_handler); sig_ignore(sig_pipe); if (phccmax) if (ipsvd_phcc_init(cmax) == -1) die_nomem(); if (str_equal(host, "")) host ="0.0.0.0"; if (str_equal(host, "0")) host ="0.0.0.0"; if (! ipsvd_scan_port(local_port, "tcp", &port)) strerr_die3x(100, FATAL, "unknown port number or name: ", local_port); if (! stralloc_copys(&sa, host)) die_nomem(); if ((dns_ip4(&ips, &sa) == -1) || (ips.len < 4)) if (dns_ip4_qualify(&ips, &fqdn, &sa) == -1) fatal2("unable to look up ip address", host); if (ips.len < 4) strerr_die3x(100, FATAL, "unable to look up ip address: ", host); ips.len =4; if (! stralloc_0(&ips)) die_nomem(); local_ip[ipsvd_fmt_ip(local_ip, ips.s)] =0; if (! lookuphost) { if (! stralloc_copys(&remote_hostname, "")) die_nomem(); if (! stralloc_0(&remote_hostname)) die_nomem(); } if ((s =socket_tcp()) == -1) fatal("unable to create socket"); if (socket_bind4_reuse(s, ips.s, port) == -1) fatal("unable to bind socket"); if (listen(s, backlog) == -1) fatal("unable to listen"); ndelay_off(s); #ifdef SSLSVD #else if (user) { /* drop permissions */ if (setgroups(ugid.gids, ugid.gid) == -1) fatal("unable to set groups"); if (setgid(*ugid.gid) == -1) fatal("unable to set gid"); if (prot_uid(ugid.uid) == -1) fatal("unable to set uid"); } #endif close(0); if (verbose) { out(INFO); out("listening on "); outfix(local_ip); out(":"); outfix(local_port); #ifdef SSLSVD #else if (user) { bufnum[fmt_ulong(bufnum, (unsigned long)ugid.uid)] =0; out(", uid "); out(bufnum); bufnum[fmt_ulong(bufnum, (unsigned long)ugid.gid)] =0; out(", gid "); out(bufnum); } #endif flush(", starting.\n"); } for (;;) { while (cnum >= cmax) sig_pause(); socka_size =sizeof(socka); sig_unblock(sig_child); conn =accept(s, (struct sockaddr *)&socka, &socka_size); sig_block(sig_child); if (conn == -1) { if (errno != error_intr) warn("unable to accept connection"); continue; } cnum++; if (verbose) connection_status(); if (phccmax) phcc =ipsvd_phcc_add((char*)&socka.sin_addr); if ((pid =fork()) == -1) { warn2("drop connection", "unable to fork"); close(conn); continue; } if (pid == 0) { /* child */ close(s); #ifdef SSLSVD if (*progname) *progname ='\\'; #endif connection_accept(conn); } if (phccmax) ipsvd_phcc_setpid(pid); close(conn); } _exit(0); }
int server(unsigned short port, int demarcaciones, int taxPorDemarcacion, int iters, int timeout_millis, int txdelay_millis, bool debug) { connection_t conn; packet_t outgoing; packet_t * incoming; if (!connection_server(&conn, port)) { fprintf(stderr, "Unable to spawn server on port %u: ", port); connection_error(&conn, stderr); fprintf(stderr, "\n"); return 1; } if (debug) { connection_debug(&conn, stderr); } gestion_taxi_t * taxis = calloc(demarcaciones * taxPorDemarcacion, sizeof(gestion_taxi_t)); if (taxis == NULL) { fprintf(stderr, "Failed to allocate memory for taxi stats structure: %s\n", strerror(errno)); return 1; } fprintf(stderr, "Waiting for clientes at port: [%d]\n", port); int connected = 0; int pendingAccAck = demarcaciones * taxPorDemarcacion; while (pendingAccAck > 0) { if (!connection_receive(&conn, &incoming, NULL)) { /* TODO: check how to safely implement a timeout here */ fprintf(stderr, "Error receiving login packet: "); connection_error(&conn, stderr); fprintf(stderr, "\n"); if (connection_dead(&conn)) { connection_close(&conn); free(taxis); return 1; } continue; } bool duplicate = false; int pos; switch (incoming->type) { case PACKET_TYPE_LOGIN: if (incoming->login.version != PACKET_VERSION) { fprintf(stderr, "Got LOGIN with version %08X but server version is %08X\n", incoming->login.version, PACKET_VERSION); connection_discard(&conn); continue; } connection_accept(&conn); for (pos = 0; pos < connected; pos++) { if (connection_cmp(&taxis[pos].conexionConTaxi, &conn)) { duplicate = true; fprintf(stderr, "Got duplicated login packet from taxi %d-%d. Re-sending acknowledgement\n", pos / taxPorDemarcacion, pos % taxPorDemarcacion); break; } } if (!duplicate) { if (connected == taxPorDemarcacion * demarcaciones) { fprintf(stderr, "Received new LOGIN but all taxis have been already registered\n"); continue; } fprintf(stderr, "Registered new taxi %d-%d\n", connected / taxPorDemarcacion, connected % taxPorDemarcacion); memcpy(&taxis[connected].conexionConTaxi, &conn, sizeof(conn)); connected++; } outgoing.type = PACKET_TYPE_ACCEPT; outgoing.accept.zone = pos / taxPorDemarcacion; outgoing.accept.id = pos % taxPorDemarcacion; outgoing.accept.neighbors = taxPorDemarcacion - 1; outgoing.accept.ticks = iters; outgoing.accept.timeout = timeout_millis; outgoing.accept.txdelay = txdelay_millis; if (!connection_send(&conn, &outgoing)) { fprintf(stderr, "Error replying to login packet: "); connection_error(&conn, stderr); fprintf(stderr, "\n"); connection_close(&conn); free(taxis); return 1; } break; case PACKET_TYPE_ACCACK: if (incoming->accack.zone >= demarcaciones || incoming->accack.id >= taxPorDemarcacion) { fprintf(stderr, "Received illegal accept acknowledgement from taxi %u-%u\n", incoming->accack.zone, incoming->accack.id); connection_discard(&conn); continue; } connection_accept(&conn); gestion_taxi_t * taxi = &taxis[incoming->accack.zone * taxPorDemarcacion + incoming->accack.id]; if (!taxi->hasAckdAccept) { taxi->hasAckdAccept = true; pendingAccAck--; } break; default: connection_discard(&conn); fprintf(stderr, "Unexpected packet %s during login phase. Discarding.\n", packet_name(incoming)); continue; } } outgoing.type = PACKET_TYPE_START; for (int pos = 0; pos < demarcaciones * taxPorDemarcacion; pos++) { if (!connection_send(&taxis[pos].conexionConTaxi, &outgoing)) { fprintf(stderr, "Error sending start packet: "); connection_error(&conn, stderr); fprintf(stderr, "\n"); connection_close(&conn); free(taxis); return 1; } } int statsRcv = 0; struct timeval defaulttimeout = { (timeout_millis * 2) / 1000, ((timeout_millis * 2) % 1000) * 1000 }; struct timeval timeout = defaulttimeout; while (statsRcv < demarcaciones * taxPorDemarcacion) { if (!connection_receive(&conn, &incoming, NULL)) { fprintf(stderr, "Error receiving packet in main loop: "); connection_error(&conn, stderr); fprintf(stderr, "\n"); if (conn.err == CONNERR_TIMEOUT) { break; } if (connection_dead(&conn)) { connection_close(&conn); free(taxis); return 1; } continue; } gestion_taxi_t * taxi; switch (incoming->type) { case PACKET_TYPE_ACCACK: outgoing.type = PACKET_TYPE_START; if (!connection_send(&conn, &outgoing)) { fprintf(stderr, "Failed to send start packet in main loop: "); connection_error(&conn, stderr); fprintf(stderr, "\n"); connection_close(&conn); return 1; } timeout = defaulttimeout; break; case PACKET_TYPE_POSITION: if (incoming->position.zone > demarcaciones || incoming->position.id > taxPorDemarcacion) { fprintf(stderr, "Received position from illegal taxi %u-%u\n", outgoing.position.zone, outgoing.position.id); connection_discard(&conn); continue; } for (int neighbor = 0; neighbor < taxPorDemarcacion; neighbor++) { if (neighbor == incoming->position.id) { continue; } if (!connection_send(&taxis[incoming->position.zone * taxPorDemarcacion + neighbor].conexionConTaxi, incoming)) { fprintf(stderr, "Error forwarding position packet: "); connection_error(&taxis[incoming->position.zone * taxPorDemarcacion + neighbor].conexionConTaxi, stderr); fprintf(stderr, "\n"); connection_close(&conn); free(taxis); return 1; } } timeout = defaulttimeout; connection_accept(&conn); break; case PACKET_TYPE_POSACK: if (incoming->posack.zone > demarcaciones || incoming->posack.id > taxPorDemarcacion) { fprintf(stderr, "Received acknowledgement from illegal taxi %u-%u\n", incoming->posack.zone, incoming->posack.id); break; } if (incoming->posack.neighbor > taxPorDemarcacion) { fprintf(stderr, "Received acknowledgement from %u-%u targeting out-of-bounds taxi %u-%u\n", incoming->posack.zone, incoming->posack.id, incoming->posack.zone, incoming->posack.neighbor); break; } taxi = &taxis[incoming->posack.zone * taxPorDemarcacion + incoming->posack.neighbor]; if (!connection_send(&taxi->conexionConTaxi, incoming)) { fprintf(stderr, "Error forwarding acknowledgement packet: "); connection_error(&taxi->conexionConTaxi, stderr); fprintf(stderr, "\n"); connection_close(&conn); free(taxis); return 1; } timeout = defaulttimeout; connection_accept(&conn); break; case PACKET_TYPE_STATS: taxi = &taxis[incoming->stats.zone * taxPorDemarcacion + incoming->stats.id]; if (!taxi->hasSentStats) { printf("%u, %u, %u, %u, %u, %u, %u, %u\n", incoming->stats.zone, incoming->stats.id, incoming->stats.ticks, incoming->stats.posrcv, incoming->stats.ackrcv, incoming->stats.itmin, incoming->stats.itavg, incoming->stats.itmax ); taxi->hasSentStats = true; statsRcv++; } outgoing.type = PACKET_TYPE_STATACK; if (!connection_send(&taxi->conexionConTaxi, &outgoing)) { fprintf(stderr, "Error sending stats acknowledgement packet: "); connection_error(&taxi->conexionConTaxi, stderr); fprintf(stderr, "\n"); connection_close(&conn); free(taxis); return 1; } timeout = defaulttimeout; connection_accept(&conn); break; default: fprintf(stderr, "Unexpected packet %s during main loop\n", packet_name(incoming)); connection_discard(&conn); continue; } } // TODO: Interpretar estadísticas return 0; }