static int ldap_pvt_connect(LDAP *ld, ber_socket_t s, struct sockaddr_un *sa, int async) { int rc; struct timeval tv, *opt_tv = NULL; if ( ld->ld_options.ldo_tm_net.tv_sec >= 0 ) { tv = ld->ld_options.ldo_tm_net; opt_tv = &tv; } oslocal_debug(ld, "ldap_connect_timeout: fd: %d tm: %ld async: %d\n", s, opt_tv ? tv.tv_sec : -1L, async); if ( ldap_pvt_ndelay_on(ld, s) == -1 ) return -1; if ( connect(s, (struct sockaddr *) sa, sizeof(struct sockaddr_un)) != AC_SOCKET_ERROR ) { if ( ldap_pvt_ndelay_off(ld, s) == -1 ) return -1; #ifdef LDAP_PF_LOCAL_SENDMSG /* Send a dummy message with access rights. Remote side will * obtain our uid/gid by fstat'ing this descriptor. The * descriptor permissions must match exactly, and we also * send the socket name, which must also match. */ sendcred: { int fds[2]; ber_socklen_t salen = sizeof(*sa); if (pipe(fds) == 0) { /* Abandon, noop, has no reply */ struct iovec iov; struct msghdr msg = {0}; # ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL # ifndef CMSG_SPACE # define CMSG_SPACE(len) (_CMSG_ALIGN( sizeof(struct cmsghdr)) + _CMSG_ALIGN(len) ) # endif # ifndef CMSG_LEN # define CMSG_LEN(len) (_CMSG_ALIGN( sizeof(struct cmsghdr)) + (len) ) # endif union { struct cmsghdr cm; unsigned char control[CMSG_SPACE(sizeof(int))]; } control_un; struct cmsghdr *cmsg; # endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */ msg.msg_name = NULL; msg.msg_namelen = 0; iov.iov_base = (char *) abandonPDU; iov.iov_len = sizeof abandonPDU; msg.msg_iov = &iov; msg.msg_iovlen = 1; # ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL msg.msg_control = control_un.control; msg.msg_controllen = sizeof( control_un.control ); msg.msg_flags = 0; cmsg = CMSG_FIRSTHDR( &msg ); cmsg->cmsg_len = CMSG_LEN( sizeof(int) ); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; *((int *)CMSG_DATA(cmsg)) = fds[0]; # else msg.msg_accrights = (char *)fds; msg.msg_accrightslen = sizeof(int); # endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */ getpeername( s, sa, &salen ); fchmod( fds[0], S_ISUID|S_IRWXU ); write( fds[1], sa, salen ); sendmsg( s, &msg, 0 ); close(fds[0]); close(fds[1]); } } #endif return 0; } if ( errno != EINPROGRESS && errno != EWOULDBLOCK ) return -1; #ifdef notyet if ( async ) return -2; #endif #ifdef HAVE_POLL { struct pollfd fd; int timeout = INFTIM; if( opt_tv != NULL ) timeout = TV2MILLISEC( &tv ); fd.fd = s; fd.events = POLL_WRITE; do { fd.revents = 0; rc = poll( &fd, 1, timeout ); } while( rc == AC_SOCKET_ERROR && errno == EINTR && LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_RESTART )); if( rc == AC_SOCKET_ERROR ) return rc; if( fd.revents & POLL_WRITE ) { if ( ldap_pvt_is_socket_ready(ld, s) == -1 ) return -1; if ( ldap_pvt_ndelay_off(ld, s) == -1 ) return -1; #ifdef LDAP_PF_LOCAL_SENDMSG goto sendcred; #else return ( 0 ); #endif } } #else { fd_set wfds, *z=NULL; #ifdef FD_SETSIZE if ( s >= FD_SETSIZE ) { rc = AC_SOCKET_ERROR; tcp_close( s ); ldap_pvt_set_errno( EMFILE ); return rc; } #endif do { FD_ZERO(&wfds); FD_SET(s, &wfds ); rc = select( ldap_int_tblsize, z, &wfds, z, opt_tv ? &tv : NULL ); } while( rc == AC_SOCKET_ERROR && errno == EINTR && LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_RESTART )); if( rc == AC_SOCKET_ERROR ) return rc; if ( FD_ISSET(s, &wfds) ) { if ( ldap_pvt_is_socket_ready(ld, s) == -1 ) return -1; if ( ldap_pvt_ndelay_off(ld, s) == -1 ) return -1; #ifdef LDAP_PF_LOCAL_SENDMSG goto sendcred; #else return ( 0 ); #endif } } #endif oslocal_debug(ld, "ldap_connect_timeout: timed out\n",0,0,0); ldap_pvt_set_errno( ETIMEDOUT ); return ( -1 ); }
/* process HTTP or SSDP requests */ int main(int argc, char * * argv) { int i; int shttpl = -1; /* socket for HTTP */ int sudp = -1; /* IP v4 socket for receiving SSDP */ #ifdef ENABLE_IPV6 int sudpv6 = -1; /* IP v6 socket for receiving SSDP */ #endif #ifdef ENABLE_NATPMP int * snatpmp = NULL; #endif #ifdef ENABLE_NFQUEUE int nfqh = -1; #endif #ifdef USE_IFACEWATCHER int sifacewatcher = -1; #endif int * snotify = NULL; int addr_count; LIST_HEAD(httplisthead, upnphttp) upnphttphead; struct upnphttp * e = 0; struct upnphttp * next; fd_set readset; /* for select() */ fd_set writeset; struct timeval timeout, timeofday, lasttimeofday = {0, 0}; int max_fd = -1; #ifdef USE_MINIUPNPDCTL int sctl = -1; LIST_HEAD(ctlstructhead, ctlelem) ctllisthead; struct ctlelem * ectl; struct ctlelem * ectlnext; #endif struct runtime_vars v; /* variables used for the unused-rule cleanup process */ struct rule_state * rule_list = 0; struct timeval checktime = {0, 0}; struct lan_addr_s * lan_addr; #ifdef ENABLE_6FC_SERVICE unsigned int next_pinhole_ts; #endif if(init(argc, argv, &v) != 0) return 1; /* count lan addrs */ addr_count = 0; for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next) addr_count++; if(addr_count > 0) { #ifndef ENABLE_IPV6 snotify = calloc(addr_count, sizeof(int)); #else /* one for IPv4, one for IPv6 */ snotify = calloc(addr_count * 2, sizeof(int)); #endif } #ifdef ENABLE_NATPMP if(addr_count > 0) { snatpmp = malloc(addr_count * sizeof(int)); for(i = 0; i < addr_count; i++) snatpmp[i] = -1; } #endif LIST_INIT(&upnphttphead); #ifdef USE_MINIUPNPDCTL LIST_INIT(&ctllisthead); #endif if( #ifdef ENABLE_NATPMP !GETFLAG(ENABLENATPMPMASK) && #endif !GETFLAG(ENABLEUPNPMASK) ) { syslog(LOG_ERR, "Why did you run me anyway?"); return 0; } syslog(LOG_INFO, "Starting%s%swith external interface %s", #ifdef ENABLE_NATPMP GETFLAG(ENABLENATPMPMASK) ? " NAT-PMP " : " ", #else " ", #endif GETFLAG(ENABLEUPNPMASK) ? "UPnP-IGD " : "", ext_if_name); if(GETFLAG(ENABLEUPNPMASK)) { /* open socket for HTTP connections. Listen on the 1st LAN address */ shttpl = OpenAndConfHTTPSocket((v.port > 0) ? v.port : 0); if(shttpl < 0) { syslog(LOG_ERR, "Failed to open socket for HTTP. EXITING"); return 1; } if(v.port <= 0) { struct sockaddr_in sockinfo; socklen_t len = sizeof(struct sockaddr_in); if (getsockname(shttpl, (struct sockaddr *)&sockinfo, &len) < 0) { syslog(LOG_ERR, "getsockname(): %m"); return 1; } v.port = ntohs(sockinfo.sin_port); } syslog(LOG_NOTICE, "HTTP listening on port %d", v.port); #ifdef ENABLE_IPV6 if(find_ipv6_addr(NULL, ipv6_addr_for_http_with_brackets, sizeof(ipv6_addr_for_http_with_brackets)) > 0) { syslog(LOG_NOTICE, "HTTP IPv6 address given to control points : %s", ipv6_addr_for_http_with_brackets); } else { memcpy(ipv6_addr_for_http_with_brackets, "[::1]", 6); syslog(LOG_WARNING, "no HTTP IPv6 address"); } #endif /* open socket for SSDP connections */ sudp = OpenAndConfSSDPReceiveSocket(0); if(sudp < 0) { syslog(LOG_NOTICE, "Failed to open socket for receiving SSDP. Trying to use MiniSSDPd"); if(SubmitServicesToMiniSSDPD(lan_addrs.lh_first->str, v.port) < 0) { syslog(LOG_ERR, "Failed to connect to MiniSSDPd. EXITING"); return 1; } } #ifdef ENABLE_IPV6 sudpv6 = OpenAndConfSSDPReceiveSocket(1); if(sudpv6 < 0) { syslog(LOG_WARNING, "Failed to open socket for receiving SSDP (IP v6)."); } #endif /* open socket for sending notifications */ if(OpenAndConfSSDPNotifySockets(snotify) < 0) { syslog(LOG_ERR, "Failed to open sockets for sending SSDP notify " "messages. EXITING"); return 1; } #ifdef USE_IFACEWATCHER /* open socket for kernel notifications about new network interfaces */ if (sudp >= 0) { sifacewatcher = OpenAndConfInterfaceWatchSocket(); if (sifacewatcher < 0) { syslog(LOG_ERR, "Failed to open socket for receiving network interface notifications"); } } #endif } #ifdef ENABLE_NATPMP /* open socket for NAT PMP traffic */ if(GETFLAG(ENABLENATPMPMASK)) { if(OpenAndConfNATPMPSockets(snatpmp) < 0) { syslog(LOG_ERR, "Failed to open sockets for NAT PMP."); } else { syslog(LOG_NOTICE, "Listening for NAT-PMP traffic on port %u", NATPMP_PORT); } #if 0 ScanNATPMPforExpiration(); #endif } #endif /* for miniupnpdctl */ #ifdef USE_MINIUPNPDCTL sctl = OpenAndConfCtlUnixSocket("/var/run/miniupnpd.ctl"); #endif #ifdef ENABLE_NFQUEUE if ( nfqueue != -1 && n_nfqix > 0) { nfqh = OpenAndConfNFqueue(); if(nfqh < 0) { syslog(LOG_ERR, "Failed to open fd for NFQUEUE."); return 1; } else { syslog(LOG_NOTICE, "Opened NFQUEUE %d",nfqueue); } } #endif /* main loop */ while(!quitting) { /* Correct startup_time if it was set with a RTC close to 0 */ if((startup_time<60*60*24) && (time(NULL)>60*60*24)) { set_startup_time(GETFLAG(SYSUPTIMEMASK)); } /* send public address change notifications if needed */ if(should_send_public_address_change_notif) { syslog(LOG_DEBUG, "should send external iface address change notification(s)"); #ifdef ENABLE_NATPMP if(GETFLAG(ENABLENATPMPMASK)) SendNATPMPPublicAddressChangeNotification(snatpmp, addr_count); #endif #ifdef ENABLE_EVENTS if(GETFLAG(ENABLEUPNPMASK)) { upnp_event_var_change_notify(EWanIPC); } #endif should_send_public_address_change_notif = 0; } /* Check if we need to send SSDP NOTIFY messages and do it if * needed */ if(gettimeofday(&timeofday, 0) < 0) { syslog(LOG_ERR, "gettimeofday(): %m"); timeout.tv_sec = v.notify_interval; timeout.tv_usec = 0; } else { /* the comparaison is not very precise but who cares ? */ if(timeofday.tv_sec >= (lasttimeofday.tv_sec + v.notify_interval)) { if (GETFLAG(ENABLEUPNPMASK)) SendSSDPNotifies2(snotify, (unsigned short)v.port, v.notify_interval << 1); memcpy(&lasttimeofday, &timeofday, sizeof(struct timeval)); timeout.tv_sec = v.notify_interval; timeout.tv_usec = 0; } else { timeout.tv_sec = lasttimeofday.tv_sec + v.notify_interval - timeofday.tv_sec; if(timeofday.tv_usec > lasttimeofday.tv_usec) { timeout.tv_usec = 1000000 + lasttimeofday.tv_usec - timeofday.tv_usec; timeout.tv_sec--; } else { timeout.tv_usec = lasttimeofday.tv_usec - timeofday.tv_usec; } } } /* remove unused rules */ if( v.clean_ruleset_interval && (timeofday.tv_sec >= checktime.tv_sec + v.clean_ruleset_interval)) { if(rule_list) { remove_unused_rules(rule_list); rule_list = NULL; } else { rule_list = get_upnp_rules_state_list(v.clean_ruleset_threshold); } memcpy(&checktime, &timeofday, sizeof(struct timeval)); } /* Remove expired port mappings, based on UPnP IGD LeaseDuration * or NAT-PMP lifetime) */ if(nextruletoclean_timestamp && ((unsigned int)timeofday.tv_sec >= nextruletoclean_timestamp)) { syslog(LOG_DEBUG, "cleaning expired Port Mappings"); get_upnp_rules_state_list(0); } if(nextruletoclean_timestamp && ((unsigned int)timeout.tv_sec >= (nextruletoclean_timestamp - timeofday.tv_sec))) { timeout.tv_sec = nextruletoclean_timestamp - timeofday.tv_sec; timeout.tv_usec = 0; syslog(LOG_DEBUG, "setting timeout to %u sec", (unsigned)timeout.tv_sec); } #ifdef ENABLE_NATPMP #if 0 /* Remove expired NAT-PMP mappings */ while(nextnatpmptoclean_timestamp && (timeofday.tv_sec >= nextnatpmptoclean_timestamp + startup_time)) { /*syslog(LOG_DEBUG, "cleaning expired NAT-PMP mappings");*/ if(CleanExpiredNATPMP() < 0) { syslog(LOG_ERR, "CleanExpiredNATPMP() failed"); break; } } if(nextnatpmptoclean_timestamp && timeout.tv_sec >= (nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec)) { /*syslog(LOG_DEBUG, "setting timeout to %d sec", nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec);*/ timeout.tv_sec = nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec; timeout.tv_usec = 0; } #endif #endif #ifdef ENABLE_6FC_SERVICE /* Clean up expired IPv6 PinHoles */ next_pinhole_ts = 0; upnp_clean_expired_pinholes(&next_pinhole_ts); if(next_pinhole_ts && timeout.tv_sec >= (int)(next_pinhole_ts - timeofday.tv_sec)) { timeout.tv_sec = next_pinhole_ts - timeofday.tv_sec; timeout.tv_usec = 0; } #endif /* select open sockets (SSDP, HTTP listen, and all HTTP soap sockets) */ FD_ZERO(&readset); FD_ZERO(&writeset); if (sudp >= 0) { FD_SET(sudp, &readset); max_fd = MAX( max_fd, sudp); #ifdef USE_IFACEWATCHER if (sifacewatcher >= 0) { FD_SET(sifacewatcher, &readset); max_fd = MAX(max_fd, sifacewatcher); } #endif } if (shttpl >= 0) { FD_SET(shttpl, &readset); max_fd = MAX( max_fd, shttpl); } #ifdef ENABLE_IPV6 if (sudpv6 >= 0) { FD_SET(sudpv6, &readset); max_fd = MAX( max_fd, sudpv6); } #endif #ifdef ENABLE_NFQUEUE if (nfqh >= 0) { FD_SET(nfqh, &readset); max_fd = MAX( max_fd, nfqh); } #endif i = 0; /* active HTTP connections count */ for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next) { if(e->socket >= 0) { if(e->state <= EWaitingForHttpContent) FD_SET(e->socket, &readset); else if(e->state == ESendingAndClosing) FD_SET(e->socket, &writeset); else continue; max_fd = MAX(max_fd, e->socket); i++; } } /* for debug */ #ifdef DEBUG if(i > 1) { syslog(LOG_DEBUG, "%d active incoming HTTP connections", i); } #endif #ifdef ENABLE_NATPMP for(i=0; i<addr_count; i++) { if(snatpmp[i] >= 0) { FD_SET(snatpmp[i], &readset); max_fd = MAX( max_fd, snatpmp[i]); } } #endif #ifdef USE_MINIUPNPDCTL if(sctl >= 0) { FD_SET(sctl, &readset); max_fd = MAX( max_fd, sctl); } for(ectl = ctllisthead.lh_first; ectl; ectl = ectl->entries.le_next) { if(ectl->socket >= 0) { FD_SET(ectl->socket, &readset); max_fd = MAX( max_fd, ectl->socket); } } #endif #ifdef ENABLE_EVENTS upnpevents_selectfds(&readset, &writeset, &max_fd); #endif if(select(max_fd+1, &readset, &writeset, 0, &timeout) < 0) { if(quitting) goto shutdown; if(errno == EINTR) continue; /* interrupted by a signal, start again */ syslog(LOG_ERR, "select(all): %m"); syslog(LOG_ERR, "Failed to select open sockets. EXITING"); return 1; /* very serious cause of error */ } #ifdef USE_MINIUPNPDCTL for(ectl = ctllisthead.lh_first; ectl;) { ectlnext = ectl->entries.le_next; if((ectl->socket >= 0) && FD_ISSET(ectl->socket, &readset)) { char buf[256]; int l; l = read(ectl->socket, buf, sizeof(buf)); if(l > 0) { /*write(ectl->socket, buf, l);*/ write_command_line(ectl->socket, argc, argv); write_option_list(ectl->socket); write_permlist(ectl->socket, upnppermlist, num_upnpperm); write_upnphttp_details(ectl->socket, upnphttphead.lh_first); write_ctlsockets_list(ectl->socket, ctllisthead.lh_first); write_ruleset_details(ectl->socket); #ifdef ENABLE_EVENTS write_events_details(ectl->socket); #endif /* close the socket */ close(ectl->socket); ectl->socket = -1; } else { close(ectl->socket); ectl->socket = -1; } } if(ectl->socket < 0) { LIST_REMOVE(ectl, entries); free(ectl); } ectl = ectlnext; } if((sctl >= 0) && FD_ISSET(sctl, &readset)) { int s; struct sockaddr_un clientname; struct ctlelem * tmp; socklen_t clientnamelen = sizeof(struct sockaddr_un); //syslog(LOG_DEBUG, "sctl!"); s = accept(sctl, (struct sockaddr *)&clientname, &clientnamelen); syslog(LOG_DEBUG, "sctl! : '%s'", clientname.sun_path); tmp = malloc(sizeof(struct ctlelem)); tmp->socket = s; LIST_INSERT_HEAD(&ctllisthead, tmp, entries); } #endif #ifdef ENABLE_EVENTS upnpevents_processfds(&readset, &writeset); #endif #ifdef ENABLE_NATPMP /* process NAT-PMP packets */ for(i=0; i<addr_count; i++) { if((snatpmp[i] >= 0) && FD_ISSET(snatpmp[i], &readset)) { ProcessIncomingNATPMPPacket(snatpmp[i]); } } #endif /* process SSDP packets */ if(sudp >= 0 && FD_ISSET(sudp, &readset)) { /*syslog(LOG_INFO, "Received UDP Packet");*/ ProcessSSDPRequest(sudp, (unsigned short)v.port); } #ifdef ENABLE_IPV6 if(sudpv6 >= 0 && FD_ISSET(sudpv6, &readset)) { syslog(LOG_INFO, "Received UDP Packet (IPv6)"); ProcessSSDPRequest(sudpv6, (unsigned short)v.port); } #endif #ifdef USE_IFACEWATCHER /* process kernel notifications */ if (sifacewatcher >= 0 && FD_ISSET(sifacewatcher, &readset)) ProcessInterfaceWatchNotify(sifacewatcher); #endif /* process active HTTP connections */ /* LIST_FOREACH macro is not available under linux */ for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next) { if(e->socket >= 0) { if(FD_ISSET(e->socket, &readset) || FD_ISSET(e->socket, &writeset)) { Process_upnphttp(e); } } } /* process incoming HTTP connections */ if(shttpl >= 0 && FD_ISSET(shttpl, &readset)) { int shttp; socklen_t clientnamelen; #ifdef ENABLE_IPV6 struct sockaddr_storage clientname; clientnamelen = sizeof(struct sockaddr_storage); #else struct sockaddr_in clientname; clientnamelen = sizeof(struct sockaddr_in); #endif shttp = accept(shttpl, (struct sockaddr *)&clientname, &clientnamelen); if(shttp<0) { /* ignore EAGAIN, EWOULDBLOCK, EINTR, we just try again later */ if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) syslog(LOG_ERR, "accept(http): %m"); } else { struct upnphttp * tmp = 0; char addr_str[64]; sockaddr_to_string((struct sockaddr *)&clientname, addr_str, sizeof(addr_str)); syslog(LOG_INFO, "HTTP connection from %s", addr_str); /* Create a new upnphttp object and add it to * the active upnphttp object list */ tmp = New_upnphttp(shttp); if(tmp) { #ifdef ENABLE_IPV6 if(clientname.ss_family == AF_INET) { tmp->clientaddr = ((struct sockaddr_in *)&clientname)->sin_addr; } else if(clientname.ss_family == AF_INET6) { struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&clientname; if(IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr)) { memcpy(&tmp->clientaddr, &addr->sin6_addr.s6_addr[12], 4); } else { tmp->ipv6 = 1; memcpy(&tmp->clientaddr_v6, &addr->sin6_addr, sizeof(struct in6_addr)); } } #else tmp->clientaddr = clientname.sin_addr; #endif LIST_INSERT_HEAD(&upnphttphead, tmp, entries); } else { syslog(LOG_ERR, "New_upnphttp() failed"); close(shttp); } } } #ifdef ENABLE_NFQUEUE /* process NFQ packets */ if(nfqh >= 0 && FD_ISSET(nfqh, &readset)) { /* syslog(LOG_INFO, "Received NFQUEUE Packet");*/ ProcessNFQUEUE(nfqh); } #endif /* delete finished HTTP connections */ for(e = upnphttphead.lh_first; e != NULL; ) { next = e->entries.le_next; if(e->state >= EToDelete) { LIST_REMOVE(e, entries); Delete_upnphttp(e); } e = next; } } /* end of main loop */ shutdown: /* close out open sockets */ while(upnphttphead.lh_first != NULL) { e = upnphttphead.lh_first; LIST_REMOVE(e, entries); Delete_upnphttp(e); } if (sudp >= 0) close(sudp); if (shttpl >= 0) close(shttpl); #ifdef ENABLE_IPV6 if (sudpv6 >= 0) close(sudpv6); #endif #ifdef USE_IFACEWATCHER if(sifacewatcher >= 0) close(sifacewatcher); #endif #ifdef ENABLE_NATPMP for(i=0; i<addr_count; i++) { if(snatpmp[i]>=0) { close(snatpmp[i]); snatpmp[i] = -1; } } #endif #ifdef USE_MINIUPNPDCTL if(sctl>=0) { close(sctl); sctl = -1; if(unlink("/var/run/miniupnpd.ctl") < 0) { syslog(LOG_ERR, "unlink() %m"); } } #endif if (GETFLAG(ENABLEUPNPMASK)) { #ifndef ENABLE_IPV6 if(SendSSDPGoodbye(snotify, addr_count) < 0) #else if(SendSSDPGoodbye(snotify, addr_count * 2) < 0) #endif { syslog(LOG_ERR, "Failed to broadcast good-bye notifications"); } #ifndef ENABLE_IPV6 for(i = 0; i < addr_count; i++) #else for(i = 0; i < addr_count * 2; i++) #endif close(snotify[i]); } if(pidfilename && (unlink(pidfilename) < 0)) { syslog(LOG_ERR, "Failed to remove pidfile %s: %m", pidfilename); } /* delete lists */ while(lan_addrs.lh_first != NULL) { lan_addr = lan_addrs.lh_first; LIST_REMOVE(lan_addrs.lh_first, list); free(lan_addr); } #ifdef ENABLE_NATPMP free(snatpmp); #endif free(snotify); closelog(); #ifndef DISABLE_CONFIG_FILE freeoptions(); #endif return 0; }
int main(int argc, char* argv[]) { int sockfd, fdmax, i, port; char *host; struct hostent *hp; struct sockaddr_in server_addr; fd_set master; fd_set read_fds; if (argc==4) { host = argv[1]; port = atoi(argv[2]); if(strlen(argv[3]) > NAME_SIZE){ fprintf(stderr, "User name too long"); exit(1); } else{ strcpy(username, argv[3]); printf("%s\n", username); } } else { fprintf(stderr, "usage: ./client <host> <port> <username>\n"); exit(1); } /* translate host name into peer’s IP address */ hp = gethostbyname(host); if (!hp) { fprintf(stderr, "unknown host: %s\n", host); exit(1); } if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("Socket"); exit(1); } server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port); server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); memset(server_addr.sin_zero, '\0', sizeof server_addr.sin_zero); if(connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) { perror("connect"); exit(1); } printf("%s\n", username); if(send(sockfd, username,sizeof(username), 0) < 0){ perror("name send"); exit(1); } FD_ZERO(&master); FD_ZERO(&read_fds); FD_SET(0, &master); FD_SET(sockfd, &master); fdmax = sockfd; init_interface(); while(1){ read_fds = master; if(select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1){ perror("select"); exit(4); } for(i=0; i <= fdmax; i++ ) if(FD_ISSET(i, &read_fds)) send_recv(i, sockfd); } out_printf("client-quited\n"); close(sockfd); return 0; }
void iopause(iopause_fd *x,unsigned int len,struct taia *deadline,struct taia *stamp) { struct taia t; int millisecs; double d; int i; if (taia_less(deadline,stamp)) millisecs = 0; else { t = *stamp; taia_sub(&t,deadline,&t); d = taia_approx(&t); if (d > 1000.0) d = 1000.0; millisecs = d * 1000.0 + 20.0; } for (i = 0;i < len;++i) x[i].revents = 0; #ifdef IOPAUSE_POLL poll(x,len,millisecs); /* XXX: some kernels apparently need x[0] even if len is 0 */ /* XXX: how to handle EAGAIN? are kernels really this dumb? */ /* XXX: how to handle EINVAL? when exactly can this happen? */ #else { struct timeval tv; fd_set rfds; fd_set wfds; int nfds; int fd; FD_ZERO(&rfds); FD_ZERO(&wfds); nfds = 1; for (i = 0;i < len;++i) { fd = x[i].fd; if (fd < 0) continue; if (fd >= 8 * sizeof(fd_set)) continue; /*XXX*/ if (fd >= nfds) nfds = fd + 1; if (x[i].events & IOPAUSE_READ) FD_SET(fd,&rfds); if (x[i].events & IOPAUSE_WRITE) FD_SET(fd,&wfds); } tv.tv_sec = millisecs / 1000; tv.tv_usec = 1000 * (millisecs % 1000); if (select(nfds,&rfds,&wfds,(fd_set *) 0,&tv) <= 0) return; /* XXX: for EBADF, could seek out and destroy the bad descriptor */ for (i = 0;i < len;++i) { fd = x[i].fd; if (fd < 0) continue; if (fd >= 8 * sizeof(fd_set)) continue; /*XXX*/ if (x[i].events & IOPAUSE_READ) if (FD_ISSET(fd,&rfds)) x[i].revents |= IOPAUSE_READ; if (x[i].events & IOPAUSE_WRITE) if (FD_ISSET(fd,&wfds)) x[i].revents |= IOPAUSE_WRITE; } } #endif }
int server_mode(const struct hostent *host, const unsigned int port) { /* Local variables */ socklen_t addr_length; /* Sockaddr length */ struct sockaddr_in sa; /* Socket remote target info structure */ fd_set rfds; /* File descriptor set for select() */ int i, sockfd, conn_sockfd, maxfd, err; /* listening socket fd, client socket fd, max fd number */ /* Debug message */ printf("[DEBUG] Listen on %s : %d\n", host->h_name, port); /* Compute socket bind structure */ sa.sin_family = AF_INET; sa.sin_port = htons(port); memcpy(&sa.sin_addr, host->h_addr_list[0], sizeof(sa.sin_addr)); /* Debug message */ puts("[DEBUG] Opening socket ..."); /* Open socket */ if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { /* Drop error message */ perror("socket()"); /* Return with error */ return SOCKET_ERROR; } /* Debug message */ puts("[DEBUG] Binding socket ..."); /* Bind socket to local address */ if (bind(sockfd, (struct sockaddr*) &sa, sizeof sa) == -1) { /* Drop error message */ perror("bind()"); /* Return with error */ return SOCKET_ERROR; } /* Debug message */ puts("[DEBUG] Start listening ..."); /* Start listening on socket */ if (listen(sockfd, 5) == -1) { /* Drop error message */ perror("listen()"); /* Return with error */ return SOCKET_ERROR; } /* CTRL+C FTW #meGusta */ for (;;) { /* Initialize fd_set and maxfd */ FD_ZERO(&rfds); FD_SET(sockfd, &rfds); maxfd = sockfd; /* Add all available clients into fd_set */ for (i = 0; i < NB_MAX_CLIENTS; ++i) { /* If client is available */ if (!clients[i].free) { /* Add it to fd_set */ FD_SET(clients[i].sockfd, &rfds); /* Update maxfd */ if (clients[i].sockfd > maxfd) maxfd = clients[i].sockfd; } } /* Debug message */ /*puts("[DEBUG] Clients list reloaded !");*/ switch (select(maxfd + 1, &rfds, NULL, NULL, NULL )) { case -1: /* If error */ /* Drop error message */ perror("select()"); /* Return with error */ return SELECT_ERROR; break; default: /* Socket event */ /* If event on listening socket */ if (FD_ISSET(sockfd, &rfds)) { /* Accept new incoming socket */ if ((conn_sockfd = accept(sockfd, (struct sockaddr*) &sa, &addr_length)) == -1) { /* Drop error message */ perror("accept()"); /* Return with error */ return SOCKET_ERROR; } /* Process new incoming socket */ if ((err = accept_client(conn_sockfd)) != NO_ERROR) return err; } /* Process event on other sockets */ for (i = 0; i < NB_MAX_CLIENTS; ++i) { /* If client is available */ if (!clients[i].free) { /* If event from client */ if (FD_ISSET(clients[i].sockfd, &rfds)) { /* Process client */ if ((err = process_client(i)) != NO_ERROR) return err; } } } break; } } /* Close socket */ close(sockfd); /* Return without error */ return NO_ERROR; }
///\brief Opens joystick port, reads from port and publishes while node is active int main(int argc, char **argv) { diagnostic_.add("Joystick Driver Status", this, &Joystick::diagnostics); diagnostic_.setHardwareID("none"); // Parameters ros::NodeHandle nh_param("~"); pub_ = nh_.advertise<sensor_msgs::Joy>("joy", 1); nh_param.param<std::string>("dev", joy_dev_, "/dev/input/js0"); nh_param.param<double>("deadzone", deadzone_, 0.05); nh_param.param<double>("autorepeat_rate", autorepeat_rate_, 0); nh_param.param<double>("coalesce_interval", coalesce_interval_, 0.001); nh_param.param<double>("max_period_with_no_events", max_period_with_no_events_, 0.5); // Checks on parameters if (autorepeat_rate_ > 1 / coalesce_interval_) ROS_WARN("joy_node: autorepeat_rate (%f Hz) > 1/coalesce_interval (%f Hz) does not make sense. Timing behavior is not well defined.", autorepeat_rate_, 1/coalesce_interval_); if (deadzone_ >= 1) { ROS_WARN("joy_node: deadzone greater than 1 was requested. The semantics of deadzone have changed. It is now related to the range [-1:1] instead of [-32767:32767]. For now I am dividing your deadzone by 32767, but this behavior is deprecated so you need to update your launch file."); deadzone_ /= 32767; } if (deadzone_ > 0.9) { ROS_WARN("joy_node: deadzone (%f) greater than 0.9, setting it to 0.9", deadzone_); deadzone_ = 0.9; } if (deadzone_ < 0) { ROS_WARN("joy_node: deadzone_ (%f) less than 0, setting to 0.", deadzone_); deadzone_ = 0; } if (autorepeat_rate_ < 0) { ROS_WARN("joy_node: autorepeat_rate (%f) less than 0, setting to 0.", autorepeat_rate_); autorepeat_rate_ = 0; } if (coalesce_interval_ < 0) { ROS_WARN("joy_node: coalesce_interval (%f) less than 0, setting to 0.", coalesce_interval_); coalesce_interval_ = 0; } if ((max_period_with_no_events_ < 0) || (max_period_with_no_events_ > 1.0)) { ROS_WARN("joy_node: max_period_with_no_events (%f) shoul be with [0.0, 1.0], setting to 0.", max_period_with_no_events_); max_period_with_no_events_ = 0.0; } // Parameter conversions double autorepeat_interval = 1 / autorepeat_rate_; double scale = -1. / (1. - deadzone_) / 32767.; double unscaled_deadzone = 32767. * deadzone_; js_event event; struct timeval tv; fd_set set; int joy_fd; event_count_ = 0; pub_count_ = 0; lastDiagTime_ = ros::Time::now().toSec(); const ros::Duration max_duration_with_no_events(max_period_with_no_events_); ros::Time last_event_time(0.0); // Big while loop opens, publishes while (nh_.ok()) { open_ = false; diagnostic_.force_update(); bool first_fault = true; while (true) { ros::spinOnce(); if (!nh_.ok()) goto cleanup; joy_fd = open(joy_dev_.c_str(), O_RDONLY); if (joy_fd != -1) { // There seems to be a bug in the driver or something where the // initial events that are to define the initial state of the // joystick are not the values of the joystick when it was opened // but rather the values of the joystick when it was last closed. // Opening then closing and opening again is a hack to get more // accurate initial state data. close(joy_fd); joy_fd = open(joy_dev_.c_str(), O_RDONLY); } if (joy_fd != -1) break; if (first_fault) { ROS_ERROR("Couldn't open joystick %s. Will retry every second.", joy_dev_.c_str()); first_fault = false; } sleep(1.0); diagnostic_.update(); } ROS_INFO("Opened joystick: %s. deadzone_: %f.", joy_dev_.c_str(), deadzone_); open_ = true; diagnostic_.force_update(); bool tv_set = false; bool publication_pending = false; tv.tv_sec = 1; tv.tv_usec = 0; sensor_msgs::Joy joy_msg; // Here because we want to reset it on device close. while (nh_.ok()) { ros::spinOnce(); bool publish_now = false; bool publish_soon = false; FD_ZERO(&set); FD_SET(joy_fd, &set); //ROS_INFO("Select..."); int select_out = select(joy_fd+1, &set, NULL, NULL, &tv); //ROS_INFO("Tick..."); if (select_out == -1) { tv.tv_sec = 0; tv.tv_usec = 0; //ROS_INFO("Select returned negative. %i", ros::isShuttingDown()); continue; // break; // Joystick is probably closed. Not sure if this case is useful. } if (FD_ISSET(joy_fd, &set)) { if (read(joy_fd, &event, sizeof(js_event)) == -1 && errno != EAGAIN) break; // Joystick is probably closed. Definitely occurs. //ROS_INFO("Read data..."); joy_msg.header.stamp = ros::Time().now(); event_count_++; switch(event.type) { case JS_EVENT_BUTTON: case JS_EVENT_BUTTON | JS_EVENT_INIT: if(event.number >= joy_msg.buttons.size()) { int old_size = joy_msg.buttons.size(); joy_msg.buttons.resize(event.number+1); for(unsigned int i=old_size;i<joy_msg.buttons.size();i++) joy_msg.buttons[i] = 0.0; } joy_msg.buttons[event.number] = (event.value ? 1 : 0); // For initial events, wait a bit before sending to try to catch // all the initial events. if (!(event.type & JS_EVENT_INIT)) { publish_now = true; last_event_time = ros::Time::now(); } else publish_soon = true; break; case JS_EVENT_AXIS: case JS_EVENT_AXIS | JS_EVENT_INIT: if(event.number >= joy_msg.axes.size()) { int old_size = joy_msg.axes.size(); joy_msg.axes.resize(event.number+1); for(unsigned int i=old_size;i<joy_msg.axes.size();i++) joy_msg.axes[i] = 0.0; } if (!(event.type & JS_EVENT_INIT)) // Init event.value is wrong. { double val = event.value; // Allows deadzone to be "smooth" if (val > unscaled_deadzone) val -= unscaled_deadzone; else if (val < -unscaled_deadzone) val += unscaled_deadzone; else val = 0; joy_msg.axes[event.number] = val * scale; } // Will wait a bit before sending to try to combine events. publish_soon = true; last_event_time = ros::Time::now(); break; default: ROS_WARN("joy_node: Unknown event type. Please file a ticket. time=%u, value=%d, type=%Xh, number=%d", event.time, event.value, event.type, event.number); break; } } else if (tv_set) // Assume that the timer has expired. publish_now = true; if (publish_now) { // Assume that all the JS_EVENT_INIT messages have arrived already. // This should be the case as the kernel sends them along as soon as // the device opens. //ROS_INFO("Publish..."); //pub_.publish(joy_msg); publish_now = false; tv_set = false; publication_pending = false; publish_soon = false; //pub_count_++; if ((ros::Time::now() - last_event_time) < max_duration_with_no_events) { pub_.publish(joy_msg); pub_count_++; } } // If an axis event occurred, start a timer to combine with other // events. if (!publication_pending && publish_soon) { tv.tv_sec = trunc(coalesce_interval_); tv.tv_usec = (coalesce_interval_ - tv.tv_sec) * 1e6; publication_pending = true; tv_set = true; //ROS_INFO("Pub pending..."); } // If nothing is going on, start a timer to do autorepeat. if (!tv_set && autorepeat_rate_ > 0) { tv.tv_sec = trunc(autorepeat_interval); tv.tv_usec = (autorepeat_interval - tv.tv_sec) * 1e6; tv_set = true; //ROS_INFO("Autorepeat pending... %i %i", tv.tv_sec, tv.tv_usec); } if (!tv_set) { tv.tv_sec = 1; tv.tv_usec = 0; } diagnostic_.update(); } // End of joystick open loop. close(joy_fd); ros::spinOnce(); if (nh_.ok()) ROS_ERROR("Connection to joystick device lost unexpectedly. Will reopen."); } cleanup: ROS_INFO("joy_node shut down."); return 0; }
// GLIB loop intergration workaround int Main::EcoreSelectInterceptor(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) { #if 0 // Check each descriptor to see if it is valid for (int i = 0; i < nfds; i++) { if (FD_ISSET(i, readfds) || FD_ISSET(i, writefds) || FD_ISSET(i, exceptfds)) { // Try to get descriptor flags int result = fcntl(i, F_GETFL); if (result == -1) { if (errno == EBADF) { // This a bad descriptor. Remove all occurrences of it. if (FD_ISSET(i, readfds)) { LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad read descriptor: " << i); FD_CLR(i, readfds); } if (FD_ISSET(i, writefds)) { LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad write descriptor: " << i); FD_CLR(i, writefds); } if (FD_ISSET(i, exceptfds)) { LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad exception descriptor: " << i); FD_CLR(i, exceptfds); } } else { // Unexpected error Assert(0); } } } } // Find out new maximum int newNfds = 0; for (int i = 0; i < nfds; i++) { if (FD_ISSET(i, readfds) || FD_ISSET(i, writefds) || FD_ISSET(i, exceptfds)) newNfds = i; } return MainSingleton::Instance().m_oldEcoreSelect(newNfds + 1, readfds, writefds, exceptfds, timeout); #else // We have to check error code here and make another try because of some glib error's. fd_set rfds, wfds, efds; memcpy(&rfds, readfds, sizeof(fd_set)); memcpy(&wfds, writefds, sizeof(fd_set)); memcpy(&efds, exceptfds, sizeof(fd_set)); int ret = MainSingleton::Instance().m_oldEcoreSelect(nfds, readfds, writefds, exceptfds, timeout); if (ret == -1) { // Check each descriptor to see if it is valid for (int i = 0; i < nfds; i++) { if (FD_ISSET(i, readfds) || FD_ISSET(i, writefds) || FD_ISSET(i, exceptfds)) { // Try to get descriptor flags int result = fcntl(i, F_GETFL); if (result == -1) { if (errno == EBADF) { // This a bad descriptor. Remove all occurrences of it. if (FD_ISSET(i, readfds)) { LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad read descriptor: " << i); FD_CLR(i, readfds); } if (FD_ISSET(i, writefds)) { LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad write descriptor: " << i); FD_CLR(i, writefds); } if (FD_ISSET(i, exceptfds)) { LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad exception descriptor: " << i); FD_CLR(i, exceptfds); } } else { // Unexpected error Assert(0); } } } } LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad read descriptor. Retrying with default select."); //Retry with old values and return new error memcpy(readfds, &rfds, sizeof(fd_set)); memcpy(writefds, &wfds, sizeof(fd_set)); memcpy(exceptfds, &efds, sizeof(fd_set)); // Trying to do it very short timeval tm; tm.tv_sec = 0; tm.tv_usec = 10; if (timeout) ret = select(nfds, readfds, writefds, exceptfds, &tm); else ret = select(nfds, readfds, writefds, exceptfds, NULL); } return ret; #endif }
int main(int argc, char **argv) { int fd = socket(AF_INET, SOCK_STREAM, 0); // TCP int on = 1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on); struct sockaddr_in srvaddr; bzero(&srvaddr, sizeof srvaddr); srvaddr.sin_family = AF_INET; srvaddr.sin_addr.s_addr = inet_addr(HOST); srvaddr.sin_port = htons(DEFAULT_PORT); if(connect(fd, (struct sockaddr *)&srvaddr, sizeof srvaddr) == -1) { perror("connect() error"); exit(1); } struct sockaddr_in myaddr; socklen_t len = sizeof myaddr; bzero(&myaddr, len); getsockname(fd, (struct sockaddr *)&myaddr, &len); printf("my port: %hu\n", htons(myaddr.sin_port)); //pthread_t tid; //pthread_create(&tid, NULL, routine, (void *)fd); char buf[100]; fd_set rset, wset, eset; // 这些是描述符集合 struct timeval a; a.tv_sec = 0; a.tv_usec = 0; while(1) { #if 0 FD_ZERO(&rset); // 添加在这里面的描述符,我们关注他们的“读就绪”状态 FD_ZERO(&wset); // 添加在这里面的描述符,我们关注他们的“写就绪”状态 FD_ZERO(&eset); // 添加在这里面的描述符,我们关注他们的“异常就绪”状态 FD_SET(fd, &rset); FD_SET(STDIN_FILENO, &rset); // 将两个描述符添加到rset里面! select(fd+1, &rset, &wset, &eset, &a); bzero(&buf, 100); if(FD_ISSET(STDIN_FILENO, &rset)) // 用户输入数据了! { fgets(buf, 100, stdin); write(fd, buf, strlen(buf)); } #endif FD_ZERO(&rset); // 添加在这里面的描述符,我们关注他们的“读就绪”状态 FD_ZERO(&wset); // 添加在这里面的描述符,我们关注他们的“写就绪”状态 FD_ZERO(&eset); // 添加在这里面的描述符,我们关注他们的“异常就绪”状态 FD_SET(fd, &rset); FD_SET(STDIN_FILENO, &rset); // 将两个描述符添加到rset里面! select(fd+1, &rset, &wset, &eset, &a); char buf[100]; bzero(buf, 100); if(FD_ISSET(fd, &rset)) // 对方有消息来了! { if(read(fd, buf, 100) == 0) break; printf("broadcast: %s\n", buf); } if(FD_ISSET(STDIN_FILENO, &rset)) // 用户输入数据了! { fgets(buf, 100, stdin); write(fd, buf, strlen(buf)); } } return 0; }
/* * Set the date in the machines controlled by timedaemons by communicating the * new date to the local timedaemon. If the timedaemon is in the master state, * it performs the correction on all slaves. If it is in the slave state, it * notifies the master that a correction is needed. * Returns 0 on success. Returns > 0 on failure, setting retval to 2; */ int netsettime(time_t tval) { struct timeval tout; struct servent *sp; struct tsp msg; struct sockaddr_in lsin, dest, from; fd_set ready; long waittime; int s, port, timed_ack, found, lerr; socklen_t length; char hostname[MAXHOSTNAMELEN]; if ((sp = getservbyname("timed", "udp")) == NULL) { warnx("timed/udp: unknown service"); return (retval = 2); } dest.sin_port = sp->s_port; dest.sin_family = AF_INET; dest.sin_addr.s_addr = htonl((u_long)INADDR_ANY); s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { if (errno != EPROTONOSUPPORT) warn("timed"); return (retval = 2); } memset(&lsin, 0, sizeof(lsin)); lsin.sin_family = AF_INET; for (port = IPPORT_RESERVED - 1; port > IPPORT_RESERVED / 2; port--) { lsin.sin_port = htons((u_short)port); if (bind(s, (struct sockaddr *)&lsin, sizeof(lsin)) >= 0) break; if (errno == EADDRINUSE) continue; if (errno != EADDRNOTAVAIL) warn("bind"); goto bad; } if (port == IPPORT_RESERVED / 2) { warnx("all ports in use"); goto bad; } memset(&msg, 0, sizeof(msg)); msg.tsp_type = TSP_SETDATE; msg.tsp_vers = TSPVERSION; if (gethostname(hostname, sizeof(hostname))) { warn("gethostname"); goto bad; } (void)strlcpy(msg.tsp_name, hostname, sizeof(msg.tsp_name)); msg.tsp_seq = htons((u_short)0); msg.tsp_time.tv_sec = htonl((u_long)tval); msg.tsp_time.tv_usec = htonl((u_long)0); length = sizeof(struct sockaddr_in); if (connect(s, (struct sockaddr *)&dest, length) < 0) { warn("connect"); goto bad; } if (send(s, (char *)&msg, sizeof(struct tsp), 0) < 0) { if (errno != ECONNREFUSED) warn("send"); goto bad; } timed_ack = -1; waittime = WAITACK; loop: tout.tv_sec = waittime; tout.tv_usec = 0; FD_ZERO(&ready); FD_SET(s, &ready); found = select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout); length = sizeof(lerr); if (!getsockopt(s, SOL_SOCKET, SO_ERROR, (char *)&lerr, &length) && lerr) { if (lerr != ECONNREFUSED) warnc(lerr, "send (delayed error)"); goto bad; } if (found > 0 && FD_ISSET(s, &ready)) { length = sizeof(struct sockaddr_in); if (recvfrom(s, &msg, sizeof(struct tsp), 0, (struct sockaddr *)&from, &length) < 0) { if (errno != ECONNREFUSED) warn("recvfrom"); goto bad; } msg.tsp_seq = ntohs(msg.tsp_seq); msg.tsp_time.tv_sec = ntohl(msg.tsp_time.tv_sec); msg.tsp_time.tv_usec = ntohl(msg.tsp_time.tv_usec); switch (msg.tsp_type) { case TSP_ACK: timed_ack = TSP_ACK; waittime = WAITDATEACK; goto loop; case TSP_DATEACK: (void)close(s); return (0); default: warnx("wrong ack received from timed: %s", tsptype[msg.tsp_type]); timed_ack = -1; break; } } if (timed_ack == -1) warnx("can't reach time daemon, time set locally"); bad: (void)close(s); return (retval = 2); }
void HttpServer::WaitMessage(uint32_t ms) { fd_set fdsr; struct timeval tv; int max_sock = m_sock; tv.tv_sec = ms / 1000; tv.tv_usec = (ms % 1000 ) / 1000; FD_ZERO(&fdsr); #ifdef _WIN32 /* on Windows, a socket is not an int but a SOCKET (unsigned int) */ FD_SET((SOCKET)m_sock, &fdsr); #else FD_SET(m_sock, &fdsr); #endif for(std::list<int>::iterator it = m_clients.begin() ; it != m_clients.end() ; ++it) { #ifdef _WIN32 FD_SET((SOCKET)(*it), &fdsr); #else FD_SET((*it), &fdsr); #endif if((*it) > max_sock) { max_sock = (*it); } } max_sock++; if(select(max_sock, &fdsr, NULL, NULL, ms ? &tv : NULL) > 0) { if(FD_ISSET(m_sock, &fdsr)) { Accept(); } for(std::list<int>::iterator it = m_clients.begin() ; it != m_clients.end() ; ++it) { if(FD_ISSET((*it), &fdsr)) { Recv((*it)); } } /* remove disconnect socket descriptor */ for(std::list<int>::iterator it = m_purge.begin() ; it != m_purge.end() ; ++it) { m_clients.remove((*it)); m_httpmsgs.erase((*it)); } /* purge disconnected list */ m_purge.erase(m_purge.begin(), m_purge.end()); } else { /* error */ } }
char *Sys_ConsoleInput( void ) { // we use this when sending back commands static char text[256]; int i; int avail; char key; field_t *history; if ( ttycon && ttycon->value ) { avail = read( 0, &key, 1 ); if ( avail != -1 ) { // we have something // backspace? // NOTE TTimo testing a lot of values .. seems it's the only way to get it to work everywhere if ( ( key == tty_erase ) || ( key == 127 ) || ( key == 8 ) ) { if ( tty_con.cursor > 0 ) { tty_con.cursor--; tty_con.buffer[tty_con.cursor] = '\0'; tty_Back(); } return NULL; } // check if this is a control char if ( ( key ) && ( key ) < ' ' ) { if ( key == '\n' ) { // push it in history Hist_Add( &tty_con ); strcpy( text, tty_con.buffer ); Field_Clear( &tty_con ); key = '\n'; write( 1, &key, 1 ); return text; } if ( key == '\t' ) { tty_Hide(); Field_CompleteCommand( &tty_con ); // Field_CompleteCommand does weird things to the string, do a cleanup // it adds a '\' at the beginning of the string // cursor doesn't reflect actual length of the string that's sent back tty_con.cursor = strlen( tty_con.buffer ); if ( tty_con.cursor > 0 ) { if ( tty_con.buffer[0] == '\\' ) { for ( i = 0; i <= tty_con.cursor; i++ ) { tty_con.buffer[i] = tty_con.buffer[i + 1]; } tty_con.cursor--; } } tty_Show(); return NULL; } avail = read( 0, &key, 1 ); if ( avail != -1 ) { // VT 100 keys if ( key == '[' || key == 'O' ) { avail = read( 0, &key, 1 ); if ( avail != -1 ) { switch ( key ) { case 'A': history = Hist_Prev(); if ( history ) { tty_Hide(); tty_con = *history; tty_Show(); } tty_FlushIn(); return NULL; break; case 'B': history = Hist_Next(); tty_Hide(); if ( history ) { tty_con = *history; } else { Field_Clear( &tty_con ); } tty_Show(); tty_FlushIn(); return NULL; break; case 'C': return NULL; case 'D': return NULL; } } } } Com_DPrintf( "droping ISCTL sequence: %d, tty_erase: %d\n", key, tty_erase ); tty_FlushIn(); return NULL; } // push regular character tty_con.buffer[tty_con.cursor] = key; tty_con.cursor++; // print the current line (this is differential) write( 1, &key, 1 ); } return NULL; } else { int len; fd_set fdset; struct timeval timeout; if ( !com_dedicated || !com_dedicated->value ) { return NULL; } if ( !stdin_active ) { return NULL; } FD_ZERO( &fdset ); FD_SET( 0, &fdset ); // stdin timeout.tv_sec = 0; timeout.tv_usec = 0; if ( select( 1, &fdset, NULL, NULL, &timeout ) == -1 || !FD_ISSET( 0, &fdset ) ) { return NULL; } len = read( 0, text, sizeof( text ) ); if ( len == 0 ) { // eof! stdin_active = qfalse; return NULL; } if ( len < 1 ) { return NULL; } text[len - 1] = 0; // rip off the /n and terminate return text; } }
void gwrl_bkd_gather(gwrl * rl) { int res = 0; gwrlevt_flags_t newflags = 0; fd_set fds[3]; gwrlsrc * src = NULL; gwrlsrc_file * fsrc = NULL; gwrlevt * evt = NULL; gwrlbkd * bkd = rl->backend; gwrlbkd_select * sbkd = _gwrlbkds(bkd); //setup timeout for select struct timeval timeout; struct timeval * timeoutp = &timeout; if(bkd->timeout.tv_sec == sec_min && bkd->timeout.tv_nsec == nsec_min) { timeoutp = NULL; } else { gwtm_timespec_to_timeval(&bkd->timeout,&timeout); } //if sleep isn't allowed set timeout to 0 if(!timeoutp && flisset(rl->flags,GWRL_NOSLEEP)) { timeoutp = &timeout; timeout.tv_sec = 0; timeout.tv_usec = 0; #ifdef GWRL_COVERAGE_INTERNAL_ASSERT_VARS if(asserts_var1 == gwrlbkd_no_sleep_assert_true) { asserts_var2 = true; } #endif } //initialize fds FD_ZERO(&(fds[0])); FD_ZERO(&(fds[1])); FD_ZERO(&(fds[2])); //reset fds memcpy(&(fds[0]),&(sbkd->src[0]),sizeof(fd_set)); memcpy(&(fds[1]),&(sbkd->src[1]),sizeof(fd_set)); memcpy(&(fds[2]),&(sbkd->src[2]),sizeof(fd_set)); //call select, wrapped in sleeping flags so other threads can wake us flset(rl->flags,GWRL_SLEEPING); res = select(sbkd->maxfd+1,&(fds[0]),&(fds[1]),&(fds[2]),timeoutp); flclr(rl->flags,GWRL_SLEEPING); if(res == 0) return; //timeout //break and let the event loop continue or start over. //if a signal did happen, the event loop may have an //event that needs processing. if(res < 0 && (errno == EINTR || errno == EAGAIN)) return; //bad fd, unforunately select doesn't tell us which //one it was so we have to search for it. if(res < 0 && errno == EBADF) { gwrl_src_file_find_badfd_post_evt(rl); return; } //invalid timeout or invalid number of fds. if(res < 0 && errno == EINVAL) { //invalid timeout, break and let process events recalculate timeouts. if(timeout.tv_sec < 0 || timeout.tv_usec < 0) return; //nfds parameter to select() is too large, not sure how to handle fprintf(stderr,"select: file descriptor limit reached. exiting. \n"); exit(1); } //valid events are ready if(res > 0) { fsrc = _gwrlsrcf(rl->sources[GWRL_SRC_TYPE_FILE]); while(fsrc) { src = _gwrlsrc(fsrc); newflags = 0; if(!flisset(src->flags,GWRL_ENABLED)) { fsrc = _gwrlsrcf(src->next); continue; } if(FD_ISSET(fsrc->fd,&fds[0])) flset(newflags,GWRL_RD); if(FD_ISSET(fsrc->fd,&fds[1])) flset(newflags,GWRL_WR); if(FD_ISSET(fsrc->fd,&fds[2])) flset(newflags,GWRL_RD); if(newflags > 0) { evt = gwrl_evt_createp(rl,src,src->callback,src->userdata,fsrc->fd,newflags); gwrl_post_evt(rl,evt); } fsrc = _gwrlsrcf(src->next); } } }
wi_socket_t * wi_socket_wait_multiple(wi_array_t *array, wi_time_interval_t timeout) { wi_enumerator_t *enumerator; wi_socket_t *socket, *waiting_socket = NULL; struct timeval tv; fd_set rfds, wfds; int state, max_sd; tv = wi_dtotv(timeout); max_sd = -1; FD_ZERO(&rfds); FD_ZERO(&wfds); wi_array_rdlock(array); enumerator = wi_array_data_enumerator(array); while((socket = wi_enumerator_next_data(enumerator))) { if(wi_string_length(socket->buffer) > 0) { waiting_socket = socket; break; } if(socket->direction & WI_SOCKET_READ) FD_SET(socket->sd, &rfds); if(socket->direction & WI_SOCKET_WRITE) FD_SET(socket->sd, &wfds); if(socket->sd > max_sd) max_sd = socket->sd; } wi_array_unlock(array); if(waiting_socket) return waiting_socket; state = select(max_sd + 1, &rfds, &wfds, NULL, (timeout > 0.0) ? &tv : NULL); if(state < 0) { wi_error_set_errno(errno); return NULL; } wi_array_rdlock(array); enumerator = wi_array_data_enumerator(array); while((socket = wi_enumerator_next_data(enumerator))) { if(FD_ISSET(socket->sd, &rfds) || FD_ISSET(socket->sd, &wfds)) { waiting_socket = socket; break; } } wi_array_unlock(array); return waiting_socket; }
void ident_check(struct descriptor_data *d, int pulse) { fd_set fd, efd; int rc, rmt_port, our_port, len; char user[256], *p; extern struct timeval null_time; extern int port; /* * Each pulse, this checks if the ident is ready to proceed to the * next state, by calling select to see if the socket is writeable * (connected) or readable (response waiting). */ switch (STATE(d)) { case CON_IDCONING: /* waiting for connect() to finish */ if (d->ident_sock != INVALID_SOCKET) { FD_ZERO(&fd); FD_ZERO(&efd); FD_SET(d->ident_sock, &fd); FD_SET(d->ident_sock, &efd); } if ((rc = select(d->ident_sock + 1, (fd_set *) 0, &fd, &efd, &null_time)) == 0) break; else if (rc < 0) { logerror("ident check select (conning)"); STATE(d) = CON_ASKNAME; break; } if (FD_ISSET(d->ident_sock, &efd)) { /* exception, such as failure to connect */ STATE(d) = CON_ASKNAME; break; } STATE(d) = CON_IDCONED; break; case CON_IDCONED: /* connected, write request */ sprintf(buf, "%d, %d\n\r", ntohs(d->peer_port), port); len = strlen(buf); #ifdef CIRCLE_WINDOWS if (send(d->ident_sock, buf, len, 0) < 0) { #else if (write(d->ident_sock, buf, len) != len) { if (errno != EPIPE) /* read end closed (no remote identd) */ #endif logerror("ident check write (conned)"); STATE(d) = CON_ASKNAME; break; } STATE(d) = CON_IDREADING; break; case CON_IDREADING: /* waiting to read */ if (d->ident_sock != INVALID_SOCKET) { FD_ZERO(&fd); FD_ZERO(&efd); FD_SET(d->ident_sock, &fd); FD_SET(d->ident_sock, &efd); } if ((rc = select(d->ident_sock + 1, &fd, (fd_set *) 0, &efd, &null_time)) == 0) break; else if (rc < 0) { logerror("ident check select (reading)"); STATE(d) = CON_ASKNAME; break; } if (FD_ISSET(d->ident_sock, &efd)) { STATE(d) = CON_ASKNAME; break; } STATE(d) = CON_IDREAD; break; case CON_IDREAD: /* read ready, get the info */ #ifdef CIRCLE_WINDOWS if ((len = recv(d->ident_sock, buf, sizeof(buf) - 1, 0)) < 0) #else if ((len = read(d->ident_sock, buf, sizeof(buf) - 1)) < 0) #endif logerror("ident check read (read)"); else { buf[len] = '\0'; if (sscanf(buf, "%u , %u : USERID :%*[^:]:%255s", &rmt_port, &our_port, user) != 3) { /* check if error or malformed */ if (sscanf(buf, "%u , %u : ERROR : %255s", &rmt_port, &our_port, user) == 3) { sprintf(buf2, "Ident error from %s: \"%s\"", d->hostIP, user); stderr_log(buf2); } else { /* strip off trailing newline */ for (p = buf + len - 1; p > buf && ISNEWL(*p); p--) ; p[1] = '\0'; sprintf(buf2, "Malformed ident response from %s: \"%s\"", d->hostIP, buf); stderr_log(buf2); } } else { len = HOST_LENGTH - strlen(d->hostIP); if (len > 0) { strncpy(buf2, user, len - 1); buf2[len - 1] = '\0'; strcpy(d->username, buf2); } /* if len <= 0, no space for username */ } } STATE(d) = CON_ASKNAME; break; case CON_ASKNAME: /* ident complete, ask for name */ /* close up the ident socket, if one is opened. */ if (d->ident_sock != INVALID_SOCKET) { close(d->ident_sock); d->ident_sock = INVALID_SOCKET; } d->idle_tics = 0; /* extra ban check */ if ((d->host[0] != '\0' && isbanned(d->host) == BAN_ALL) || isbanned(d->hostIP)) { if (d->host[0] != '\0') { sprintf(buf, "Connection attempt denied from [%s]", d->host); } else { sprintf(buf, "Connection attempt denied from [%s]", d->hostIP); } mudlog(buf, 'S', COM_IMMORT, TRUE); close_socket(d); return; } /* SEND_TO_Q("\x1B[2K\n\rBy what name do you wish to be known? ", d); */ STATE(d) = CON_GET_TERMTYPE; return; default: return; } /* * Print a dot every second so the user knows he hasn't been forgotten. * Allow the user to go on anyways after waiting IDENT_TIMEOUT seconds. */ if ((pulse % PASSES_PER_SEC) == 0) { SEND_TO_Q(".", d); if (d->idle_tics++ >= IDENT_TIMEOUT) STATE(d) = CON_ASKNAME; } } /* returns 1 if waiting for ident to complete, else 0 */ int waiting_for_ident(struct descriptor_data *d) { switch (STATE(d)) { case CON_IDCONING: case CON_IDCONED: case CON_IDREADING: case CON_IDREAD: case CON_ASKNAME: return 1; } return 0; }
int main(int argc, char *argv[]) { pid_t child_pid; int child_exit_status; struct termios tty_attr; struct winsize window_size; int pty_master; /* for select */ fd_set readfds; fd_set writefds; unsigned err_n_rpty = 0; unsigned err_n_wpty = 0; unsigned err_n_stdin = 0; unsigned err_n_stdout = 0; int done = 0; /* the ring buffers */ char inbuf_mem[BUFSIZE]; char outbuf_mem[BUFSIZE]; struct ring_buffer inbuf; struct ring_buffer outbuf; rb_init(&inbuf, inbuf_mem, sizeof(inbuf_mem)); rb_init(&outbuf, outbuf_mem, sizeof(outbuf_mem)); if (argc == 1) { printf("usage: %s PROGRAM [ARGS]...\n", argv[0]); exit(1); } /* We need I/O calls to fail with EINTR on SIGCHLD... */ if (signal(SIGCHLD, sigchld_handler) == SIG_ERR) { perror("signal(SIGCHLD,...)"); exit(EX_OSERR); } if (isatty(STDIN_FILENO)) { /* get terminal parameters associated with stdout */ if (tcgetattr(STDOUT_FILENO, &tty_attr) < 0) { perror("tcgetattr(stdout,...)"); exit(EX_OSERR); } /* get window size */ if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &window_size) < 0) { perror("ioctl(stdout,...)"); exit(1); } child_pid = forkpty(&pty_master, NULL, &tty_attr, &window_size); } else { /* not interactive */ child_pid = forkpty(&pty_master, NULL, NULL, NULL); } if (child_pid < 0) { perror("forkpty()"); exit(EX_OSERR); } if (child_pid == 0) { /* in the child */ struct termios s_tty_attr; if (tcgetattr(STDIN_FILENO, &s_tty_attr)) { perror("tcgetattr(stdin,...)"); exit(EXIT_FAILURE); } /* Turn off echo */ s_tty_attr.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); /* Also turn of NL to CR?LF on output */ s_tty_attr.c_oflag &= ~(ONLCR); if (tcsetattr(STDIN_FILENO, TCSANOW, &s_tty_attr)) { perror("tcsetattr(stdin,...)"); exit(EXIT_FAILURE); } if (execvp(argv[1], argv + 1)) { perror("execvp()"); exit(EXIT_FAILURE); } } /* Non blocking mode for all file descriptors. */ setfd_nonblock(pty_master); setfd_nonblock(STDIN_FILENO); setfd_nonblock(STDOUT_FILENO); if (isatty(STDIN_FILENO)) { if (tty_semi_raw(STDIN_FILENO) < 0) { perror("tty_semi_raw(stdin)"); } if (atexit(tty_atexit) < 0) { perror("atexit()"); } } do { /* Accept events only on fds, that we can handle now. */ int do_select = 0; FD_ZERO(&readfds); FD_ZERO(&writefds); if (rb_space(&outbuf) > 0 && err_n_rpty < MAXRETR) { FD_SET(pty_master, &readfds); do_select = 1; } if (!rb_isempty(&inbuf) && err_n_wpty < MAXRETR) { FD_SET(pty_master, &writefds); do_select = 1; } if (rb_space(&inbuf) > 0 && err_n_stdin < MAXRETR) { FD_SET(STDIN_FILENO, &readfds); do_select = 1; } if (!rb_isempty(&outbuf) && err_n_stdout < MAXRETR) { FD_SET(STDOUT_FILENO, &writefds); do_select = 1; } if (!do_select) { #ifdef DEBUG fprintf(stderr, "No I/O job for us, calling waitpid()...\n"); #endif while (waitpid(child_pid, &child_exit_status, 0) < 0) { /* nothing */ } break; } int select_rc = select(pty_master + 1, &readfds, &writefds, NULL, NULL); if (select_rc < 0) { perror("select()"); exit(EX_IOERR); } #ifdef DEBUG fprintf(stderr, "select() returned %d\n", select_rc); #endif if (FD_ISSET(STDOUT_FILENO, &writefds)) { #ifdef DEBUG fprintf(stderr, "stdout can be written\n"); #endif ssize_t n = rb_write(&outbuf, STDOUT_FILENO); if (n <= 0 && n != EINTR && n != EAGAIN) err_n_stdout++; #ifdef DEBUG if (n >= 0) fprintf(stderr, "%d bytes written into stdout\n", n); else perror("write(stdout,...)"); #endif } if (FD_ISSET(pty_master, &writefds)) { #ifdef DEBUG fprintf(stderr, "pty_master can be written\n"); #endif ssize_t n = rb_write(&inbuf, pty_master); if (n <= 0 && n != EINTR && n != EAGAIN) err_n_wpty++; #ifdef DEBUG if (n >= 0) fprintf(stderr, "%d bytes written into pty_master\n", n); else perror("write(pty_master,...)"); #endif } if (FD_ISSET(STDIN_FILENO, &readfds)) { #ifdef DEBUG fprintf(stderr, "stdin can be read\n"); #endif ssize_t n = rb_read(&inbuf, STDIN_FILENO); if (n <= 0 && n != EINTR && n != EAGAIN) err_n_stdin++; #ifdef DEBUG if (n >= 0) fprintf(stderr, "%d bytes read from stdin\n", n); else perror("read(stdin,...)"); #endif } if (FD_ISSET(pty_master, &readfds)) { #ifdef DEBUG fprintf(stderr, "pty_master can be read\n"); #endif ssize_t n = rb_read(&outbuf, pty_master); if (n <= 0 && n != EINTR && n != EAGAIN) err_n_rpty++; #ifdef DEBUG if (n >= 0) fprintf(stderr, "%d bytes read from pty_master\n", n); else perror("read(pty_master,...)"); #endif } if (!done && waitpid(child_pid, &child_exit_status, WNOHANG) > 0) done = 1; } while (!done || !(rb_isempty(&inbuf) || err_n_wpty >= MAXRETR) || !(rb_isempty(&outbuf) || err_n_stdout >= MAXRETR)); #ifdef DEBUG fprintf(stderr, "inbuf: %u bytes left, outbuf: %u bytes left\n", inbuf.count, outbuf.count); fprintf(stderr, "err_n_rpty=%u, err_n_wpty=%u, err_n_stdin=%u, err_n_stdout=%u\n", err_n_rpty, err_n_wpty, err_n_stdin, err_n_stdout); #endif if (WIFEXITED(child_exit_status)) exit(WEXITSTATUS(child_exit_status)); else if (WIFSIGNALED(child_exit_status)) exit(128 + WTERMSIG(child_exit_status)); exit(EXIT_FAILURE); }
/* ============================================================================ Funcion principal ============================================================================ */ int main(int argc, char *argv[]) { stHeaderIPC *unHeaderIPC = NULL, *stHeaderSwitch = NULL; stMensajeIPC unMensaje; stPCB *unPCB = NULL; t_UMCConfig UMCConfig; pthread_t p_thread, p_threadCpu; char* temp_file = "nucleo.log"; elEstadoActual.path_conf = argv[1]; uint32_t pid_desconectado = 0; int unCliente = 0, maximoAnterior = 0, unSocket, agregarSock; struct sockaddr addressAceptado; /*Inicializacion de las colas del planificador*/ inicializar_pidCounter(); inicializar_cola_ready(); listaBlock = list_create(); consola_crear_lista(); log_create(temp_file, "NUCLEO", -1, LOG_LEVEL_INFO); log_info("Arrancando el Nucleo"); if (elEstadoActual.path_conf == NULL) { log_error("Falta el parametro de configuracion"); exit(-1); } /*Carga del archivo de configuracion*/ if (loadInfo(&elEstadoActual, 0)) { log_error("Error al cargar la configuracion"); exit(-2); } log_info("Configuracion cargada satisfactoriamente..."); /*Se lanza el thread para identificar cambios en el archivo de configuracion*/ pthread_create(&p_thread, NULL, &monitor_configuracion, (void*) &elEstadoActual); inicializarThreadsDispositivos(&elEstadoActual); /*Inicializacion de listas de socket*/ FD_ZERO(&(fds_master)); FD_ZERO(&(read_fds)); /*Inicializacion de socket de escucha*/ elEstadoActual.salir = 0; elEstadoActual.sockEscuchador = -1; /*Iniciando escucha en el socket escuchador de Consola*/ elEstadoActual.sockEscuchador = escuchar(elEstadoActual.miPuerto); FD_SET(elEstadoActual.sockEscuchador, &(fds_master)); log_debug("Se establecio conexion con el socket de escucha..."); /*Seteamos el maximo socket*/ elEstadoActual.fdMax = elEstadoActual.sockEscuchador; /*Conexion con el proceso UMC*/ log_debug("Estableciendo conexion con la UMC..."); elEstadoActual.sockUmc = conectar(elEstadoActual.ipUmc, elEstadoActual.puertoUmc); if (elEstadoActual.sockUmc != -1) { //FD_SET(elEstadoActual.sockUmc, &(fds_master)); unHeaderIPC = nuevoHeaderIPC(ERROR); if (!recibirHeaderIPC(elEstadoActual.sockUmc, unHeaderIPC)) { log_error("UMC handshake error - No se pudo recibir mensaje de respuesta"); log_error("No se pudo conectar a la UMC"); elEstadoActual.salir = 1; } if (unHeaderIPC->tipo == QUIENSOS) { unHeaderIPC = nuevoHeaderIPC(CONNECTNUCLEO); if (!enviarHeaderIPC(elEstadoActual.sockUmc, unHeaderIPC)) { log_error("UMC handshake error - No se pudo enviar mensaje de conexion"); log_error("No se pudo conectar a la UMC"); elEstadoActual.salir = 1; } } liberarHeaderIPC(unHeaderIPC); unHeaderIPC = nuevoHeaderIPC(OK); if (!recibirHeaderIPC(elEstadoActual.sockUmc, unHeaderIPC)) { log_error("UMC handshake error - No se pudo recibir mensaje de confirmacion"); log_error("No se pudo conectar a la UMC"); elEstadoActual.salir = 1; } else { if (recibirConfigUMC(elEstadoActual.sockUmc, &UMCConfig)) { log_error("UMC error - No se pudo recibir la configuracion"); close(unCliente); exit(-2); } agregar_master(elEstadoActual.sockUmc,maximoAnterior); log_info("Paginas por proceso:[%d]", UMCConfig.paginasXProceso); log_info("Tamanio de pagina:[%d]", UMCConfig.tamanioPagina); elEstadoActual.tamanio_paginas = UMCConfig.tamanioPagina; } liberarHeaderIPC(unHeaderIPC); } else { log_error("No se pudo conectar a la UMC"); elEstadoActual.salir = 1; } /*Ciclo Principal del Nucleo*/ log_info("............................................................................."); log_info("..............................Esperando Conexion.............................\n\n"); fflush(stdout); while (elEstadoActual.salir == 0) { read_fds = fds_master; if (seleccionar(elEstadoActual.fdMax, &read_fds, 0) == -1) { log_error("Error Preparando el Select"); break; } for (unSocket = 0; unSocket <= elEstadoActual.fdMax; unSocket++) { if (FD_ISSET(unSocket, &read_fds)) { /*Nueva conexion*/ if (unSocket == elEstadoActual.sockEscuchador) { unCliente = aceptar(elEstadoActual.sockEscuchador, &addressAceptado); unHeaderIPC = nuevoHeaderIPC(QUIENSOS); if (!enviarHeaderIPC(unCliente, unHeaderIPC)) { log_error("Cliente Handshake error - No se puede enviar el mensaje QUIENSOS"); liberarHeaderIPC(unHeaderIPC); close(unCliente); break;/*Sale del for*/ } liberarHeaderIPC(unHeaderIPC); unHeaderIPC = nuevoHeaderIPC(ERROR); if (!recibirHeaderIPC(unCliente, unHeaderIPC)) { log_error("Cliente Handshake error - No se puede recibir el mensaje"); liberarHeaderIPC(unHeaderIPC); close(unCliente); break;/*Sale del for*/ } /*Identifico quien se conecto y procedo*/ switch (unHeaderIPC->tipo) { case CONNECTCONSOLA: stHeaderSwitch = nuevoHeaderIPC(OK); if (!enviarHeaderIPC(unCliente, stHeaderSwitch)) { log_error("Handshake Consola - No se pudo enviar el OK"); liberarHeaderIPC(stHeaderSwitch); close(unCliente); break;/*Sale del switch*/ } liberarHeaderIPC(stHeaderSwitch); log_info("Nueva consola conectada"); agregarSock = 1; /*Agrego el socket conectado a la lista Master*/ if (agregarSock == 1) { agregar_master(unCliente, maximoAnterior); agregarSock = 0; } /* Recibo Programa */ if (!recibirMensajeIPC(unCliente, &unMensaje)) { log_error("No se puede recibir el programa a procesar"); break;/*Sale del switch*/ } else { if (unMensaje.header.tipo == SENDANSISOP) { /*metadata_desde_literal hace un malloc adentro*/ int cantidadDePaginasCodigo = calcular_cantidad_paginas(unMensaje.header.largo, UMCConfig.tamanioPagina); /***Creacion del PCB***/ unPCB = crear_pcb(unCliente, cantidadDePaginasCodigo, elEstadoActual.stackSize, &unMensaje); if (unPCB == NULL) { log_error("Error al crear el PCB... se cierra la consola\n"); quitar_master(unCliente, maximoAnterior); close(unCliente); break;/*Sale del switch*/ } if (inicializar_programa(unPCB, (char *)unMensaje.contenido, elEstadoActual.sockUmc) == EXIT_FAILURE) { log_error("No se pudo inicializar el programa"); quitar_master(unCliente, maximoAnterior); close(unCliente); break;/*Sale del switch*/ } /* Inicializada la consola la agrego a consolas activas */ agregar_consola(unCliente, unPCB->pid); /*Cuando se usa mensajeIPC liberar el contenido*/ free(unMensaje.contenido); ready_productor(unPCB); log_info("PCB [PID - %d] NEW a READY\n", unPCB->pid); fflush(stdout); } } break; case CONNECTCPU: stHeaderSwitch = nuevoHeaderIPC(OK); if (!enviarHeaderIPC(unCliente, stHeaderSwitch)) { liberarHeaderIPC(stHeaderSwitch); log_error("CPU error - No se pudo enviar OK"); close(unCliente); break;/*Sale del switch*/ } liberarHeaderIPC(stHeaderSwitch); if (pthread_create(&p_threadCpu, NULL, (void*) consumidor_cpu, (void*) &unCliente) != 0) { log_error("No se pudo lanzar el hilo correspondiente al cpu conectado"); close(unCliente); break;/*Sale del switch*/ } log_info("Se lanza hilo de atencion a CPU conectado"); fflush(stdout); break; default: break; } if (unHeaderIPC != NULL) { liberarHeaderIPC(unHeaderIPC); } } else { /*Conexion existente*/ log_debug("Recibi otro evento de un cliente ya conectado"); if (!recibirMensajeIPC(unSocket, &unMensaje)) { log_info("Desconexion detectada"); // Desconexion de una consola pid_desconectado = borrar_consola(unSocket); // Desconexion de la UMC if (unSocket == elEstadoActual.sockUmc) { log_info("Se perdio conexion con la UMC..."); elEstadoActual.salir = 1; cerrarSockets(&elEstadoActual); } if (unSocket == elEstadoActual.sockEscuchador) { log_debug("Se perdio conexion..."); } /*Saco el socket de la lista Master*/ quitar_master(unSocket, maximoAnterior); fflush(stdout); } } } } } destruir_planificador(); destruir_lista_dispositivos(&elEstadoActual); consola_destruir_lista(&elEstadoActual); cerrarSockets(&elEstadoActual); finalizarSistema(&unMensaje, unSocket, &elEstadoActual); log_info("Fin del programa"); return 0; }
int main(int argc, char** argv) { ipcio_t data_block = IPCIO_INIT; key_t key = DADA_DEFAULT_BLOCK_KEY; int status = 0; char eventfile[128]; FILE *infd, *evfd; //get this many bytes at a time from data socket int BUFSIZE = UDP_HDR_SIZE + VDIF_PKT_SIZE; char buf[BUFSIZE]; char dev[16] = ETHDEV; char hostname[MAXHOSTNAME]; gethostname(hostname,MAXHOSTNAME); char *starthost = strstr(hostname, "difx"); int nbytes = 0, state = STATE_STOPPED; uint64_t port = WRITER_SERVICE_PORT; //int cmd = CMD_NONE; char cmd = CMD_NONE; int ii, arg, maxsock = 0; fd_set readfds; struct timeval tv; //timeout for select()--set it to zero tv.tv_sec = 0; tv.tv_usec = 0; Connection c; c.sockoptval = 1; //release port immediately after closing connection Connection raw; raw.alen = sizeof(raw.rem_addr); raw.sockoptval = 32*1024*1024; //size of data socket internal buffer // For gathering stats on frame skips long framenumtmp, framenum[2], framediff; framenum[0] = -1; framenum[1] = -1; int threadid = -1; FILE* skiplogfd; char skiplogfile[128]; time_t currt; char currt_string[128]; struct tm *tmpt; while ((arg = getopt(argc, argv, "hk:p:e:")) != -1) { switch(arg) { case 'h': usage (); return 0; case 'k': if (sscanf (optarg, "%x", &key) != 1) { fprintf (stderr, "writer: could not parse key from %s\n", optarg); return -1; } break; case 'p': if (sscanf (optarg, "%"PRIu64"", &port) != 1) { fprintf (stderr, "writer: could not parse port from %s\n", optarg); return -1; } break; case 'e': if (sscanf (optarg, "%s", dev) != 1) { fprintf (stderr, "writer: could not parse ethernet device from %s\n", optarg); return -1; } break; } } sprintf(skiplogfile,"%s%s%s%s","skiplog-",starthost,dev,".txt"); if((skiplogfd = fopen(skiplogfile, "w")) == NULL) { fprintf(stderr,"Writer: Could not open skiplog file %s for writing.\n",skiplogfile); exit(1); } //Try to connect to existing data block if(ipcio_connect(&data_block,key) < 0) exit(1); fprintf(stderr,"after ipcio_connect\n"); //create listening socket if(serve(port, &c) < 0) { fprintf(stderr,"Writer: Failed to create listening socket.\n"); exit(1); } maxsock = c.rqst; //Open raw data stream socket raw.svc = openRawSocket(dev,0); if(raw.svc < 0) { fprintf(stderr, "Cannot open raw socket on %s. Error code %d\n", dev, raw.svc); exit(1); } setsockopt(raw.svc, SOL_SOCKET, SO_RCVBUF, (char *)&(raw.sockoptval), sizeof(raw.sockoptval)); if(raw.svc > maxsock) maxsock = raw.svc; //ii = 0; while(1) { //ii++; //printf("ii: %d state: %d cmd: %d\n",ii,state,cmd); if(state == STATE_STOPPED) { if(cmd == CMD_NONE) cmd = wait_for_cmd(&c); if(cmd == CMD_START) { state = STATE_STARTED; if(ipcio_open(&data_block,'W') < 0) exit(1); fprintf(stderr,"after ipcio_open, W\n"); cmd = CMD_NONE; } else if(cmd == CMD_EVENT) { fprintf(stderr, "Writer: ignored CMD_EVENT in STATE_STOPPED.\n"); cmd = CMD_NONE; } else if(cmd == CMD_STOP) { fprintf(stderr, "Writer: ignored CMD_STOP in STATE_STOPPED.\n"); cmd = CMD_NONE; } else if(cmd == CMD_QUIT) { shutdown(c.rqst,2); return 0; } } //if state is STARTED, poll the command listening socket and the VDIF raw data socket if(state == STATE_STARTED) { FD_ZERO(&readfds); FD_SET(c.rqst, &readfds); FD_SET(raw.svc, &readfds); select(maxsock+1,&readfds,NULL,NULL,&tv); //if input is waiting on listening socket, read it if(FD_ISSET(c.rqst,&readfds)) { cmd = wait_for_cmd(&c); } if(cmd == CMD_EVENT) { //close data block if(ipcio_close(&data_block) < 0) exit(1); fprintf(stderr,"after ipcio_close\n"); //dump DB to file currt = time(NULL); tmpt = localtime(&currt); strftime(currt_string,sizeof(currt_string), "%Y%m%d_%H%M%S", tmpt); *(currt_string+15) = 0; sprintf(eventfile,"%s/%s%s_%s_ev.out",EVENTDIR,starthost,dev,currt_string); if((evfd = fopen(eventfile,"w")) == NULL) { fprintf(stderr,"Writer: Could not open file %s for writing.\n",eventfile); } else { event_to_file(&data_block,evfd); fclose(evfd); } //Get pending commands, resume writing to ring buffer if there are none FD_ZERO(&readfds); FD_SET(c.rqst, &readfds); FD_SET(raw.svc, &readfds); select(maxsock+1,&readfds,NULL,NULL,&tv); state = STATE_STOPPED; if(FD_ISSET(c.rqst,&readfds)) { cmd = wait_for_cmd(&c); fprintf(stderr,"Writer: flushed out command socket after event_to_file.\n"); } else cmd = CMD_START; continue; } //if command is stop, change state to STOPPED, close data block else if(cmd == CMD_STOP) { state = STATE_STOPPED; if(ipcio_close(&data_block) < 0) exit(1); fprintf(stderr,"after ipcio_close\n"); cmd = CMD_NONE; continue; } //if command is quit, close data block, shutdown listening socket, return else if(cmd == CMD_QUIT) { if(ipcio_close(&data_block) < 0) exit(1); fprintf(stderr,"after ipcio_close\n"); shutdown(c.rqst,2); return 0; } else if(cmd == CMD_START) { fprintf(stderr,"Writer: ignored cmd start (already started).\n"); cmd = CMD_NONE; } //read a packet from the data socket and write it to the ring buffer if(FD_ISSET(raw.svc,&readfds)) { nbytes = recvfrom(raw.svc, buf, BUFSIZE, 0, (struct sockaddr *)&(raw.rem_addr), &(raw.alen)); if(nbytes == BUFSIZE) { //fwrite(buf + trim, recvlen-trim, 1, out); status = ipcio_write(&data_block,buf+UDP_HDR_SIZE,VDIF_PKT_SIZE); //fprintf(stderr,"ipcio_write: %d bytes\n",status); //print VDIF frame header //printVDIFHeader((vdif_header *)(buf+UDP_HDR_SIZE), VDIFHeaderPrintLevelLong); //printVDIFHeader((vdif_header *)(buf+UDP_HDR_SIZE), VDIFHeaderPrintLevelColumns); //printVDIFHeader((vdif_header *)(buf+UDP_HDR_SIZE), VDIFHeaderPrintLevelShort); //fprintf(stderr,"VDIFFrame MJD: %d Number: %d\n",getVDIFFrameMJD((vdif_header *)(buf+UDP_HDR_SIZE)), getVDIFFrameNumber((vdif_header *)(buf+UDP_HDR_SIZE))); framenumtmp = getVDIFFrameNumber((vdif_header *)(buf+UDP_HDR_SIZE)); threadid = getVDIFThreadID((vdif_header *)(buf+UDP_HDR_SIZE)); framediff = framenumtmp - framenum[threadid]; if(framediff != -MAXFRAMENUM && framenum[threadid] != -1 && framediff != 1) { //if(framediff != -25599 && abs(framediff) > 1 && framenum[threadid] != -1) { currt = time(NULL); tmpt = localtime(&currt); strftime(currt_string,sizeof(currt_string), "%Y-%m-%d %H:%M:%S", tmpt); fprintf(skiplogfd,"%s FRAME SKIP FROM %d to %d (THREAD %d)\n",currt_string,framenum[threadid],framenumtmp,threadid); fflush(skiplogfd); } else if(framenum[threadid] == -1) { fprintf(skiplogfd,"Writer: Thread %d First frame: %d\n",threadid,framenumtmp); fflush(skiplogfd); } framenum[threadid] = framenumtmp; } else if(nbytes <= 0) { fprintf(stderr,"Raw socket read failed: %d\n.", nbytes); } /* else fprintf(stderr,"Received packet size: %d, ignoring.\n", nbytes); */ } //XXX: check for overflow of the data block here? //nbytes = fread(buf,1,BUFSIZE,infd); //fprintf(stderr,"fread: %d bytes\n",nbytes); //status = ipcio_write(&data_block,buf,nbytes); //fprintf(stderr,"ipcio_write: %d bytes\n",status); //sleep(2); } } //fclose(infd); return 0; }
static void select_loop(libvchan_t *vchan) { fd_set select_set; fd_set wr_set; int max_fd; int ret; int vchan_fd; sigset_t selectmask; struct timespec zero_timeout = { 0, 0 }; struct timespec select_timeout = { 10, 0 }; struct buffer stdin_buf; sigemptyset(&selectmask); sigaddset(&selectmask, SIGCHLD); sigprocmask(SIG_BLOCK, &selectmask, NULL); sigemptyset(&selectmask); buffer_init(&stdin_buf); /* remember to set back to blocking mode before closing the FD - this may * be not the only copy and some processes may misbehave when get * nonblocking FD for input/output */ set_nonblock(local_stdin_fd); for (;;) { vchan_fd = libvchan_fd_for_select(vchan); FD_ZERO(&select_set); FD_ZERO(&wr_set); FD_SET(vchan_fd, &select_set); max_fd = vchan_fd; if (local_stdout_fd != -1 && (size_t)libvchan_buffer_space(vchan) > sizeof(struct msg_header)) { FD_SET(local_stdout_fd, &select_set); if (local_stdout_fd > max_fd) max_fd = local_stdout_fd; } if (child_exited && local_stdout_fd == -1) check_child_status(vchan); if (local_stdin_fd != -1 && buffer_len(&stdin_buf)) { FD_SET(local_stdin_fd, &wr_set); if (local_stdin_fd > max_fd) max_fd = local_stdin_fd; } if ((local_stdin_fd == -1 || buffer_len(&stdin_buf) == 0) && libvchan_data_ready(vchan) > 0) { /* check for other FDs, but exit immediately */ ret = pselect(max_fd + 1, &select_set, &wr_set, NULL, &zero_timeout, &selectmask); } else ret = pselect(max_fd + 1, &select_set, &wr_set, NULL, &select_timeout, &selectmask); if (ret < 0) { if (errno == EINTR && local_pid > 0) { continue; } else { perror("select"); do_exit(1); } } if (ret == 0) { if (!libvchan_is_open(vchan)) { /* remote disconnected witout a proper signaling */ do_exit(1); } } if (FD_ISSET(vchan_fd, &select_set)) libvchan_wait(vchan); if (buffer_len(&stdin_buf) && local_stdin_fd != -1 && FD_ISSET(local_stdin_fd, &wr_set)) { if (flush_client_data(local_stdin_fd, &stdin_buf) == WRITE_STDIN_ERROR) { perror("write stdin"); close(local_stdin_fd); local_stdin_fd = -1; } } while (libvchan_data_ready(vchan)) if (handle_vchan_data(vchan, &stdin_buf) != WRITE_STDIN_OK) break; if (local_stdout_fd != -1 && FD_ISSET(local_stdout_fd, &select_set)) handle_input(vchan); } }
void maitreClient(){ fd_set fdread; struct timeval tv; int n,i,r,m,start; #ifdef DEBUG char dbg[16]; #endif struct flock lock; int t; maitreLecteur=dp.maitre[0]; FD_ZERO(&fdread); tv.tv_sec = 50; tv.tv_usec = 0; n=fdServeur>maitreLecteur?fdServeur:maitreLecteur; printf("Maitre CLient - fdServeur=%d\n", fdServeur); while(1){ /* On ajoute les descripteurs esclave et serveur */ /* Add slave and server pipe file descriptors */ FD_ZERO(&fdread); FD_SET(fdServeur,&fdread); FD_SET(maitreLecteur,&fdread); r=select(n+1, &fdread, NULL, NULL,&tv); if(r<0){ perror("select:\n"); continue; } if(r==0){ exit(0); } if(FD_ISSET(fdServeur, &fdread)){ /* On vient de recevoir une information du serveur * On la retransmet aux esclaves */ /* We just have received information from the server. * We repeat it to slaves. */ i=readFromServer(message); t=message[0]; switch(t){ case 'L': /* Instruction : Lock. Dans ce cas il faut envoyer a chaque processus une section differente a locker */ /* Lock instruction. We need to send a different section to lock to each process */ unSerialiseFLock(&lock); start=lock.l_start; for(i=0;i<dp.nclnt;i++){ lock.l_start=start+i; serialiseFLock(&lock); write(dp.lclnt[i][1], message,M_SIZE); } printf("\n"); continue; case 'T': /* Instruction: Test. Il s'agit d'une trame annoncant un nouveau test : on verifie qu'il ne s'agit pas d'une * demande de FIN des tests */ /* Test instruction. Ensure server is not sending the FIN(ish) instruction to end tests */ /* A re-ecrire un peu mieux des que possible */ /* To be rewritten asap*/ m=atoi(&(message[2])); if(m==FIN) break; if(m==CLEAN) printf("\n"); serverSendLocal(); continue; } break; }else{ /* Dans le cas inverse, on lis les esclaves et on remonte l'information au serveur */ /* Else, we read information from slaves and repeat them to the server */ for(i=0;i<dp.nclnt;i++){ r=read(maitreLecteur, message,M_SIZE ); r=write(fdServeur,message,M_SIZE ); if(r<0)perror("write : "); } continue; } } /* On vient de recevoir la trame FIN de programme */ /* Receive the FIN(ish) instruction*/ /* On la communique a tous les esclaves */ /* Repeat it to the slaves */ printf("Fin du programme en cours...\n"); serverSendLocal(); /* Et c'est fini! */ /* Ok, we can quit */ printf("Bye :)\n"); }
void Run() { break_ = false; // configure the master fd_set for select() fd_set masterfds, tempfds; FD_ZERO( &masterfds ); FD_ZERO( &tempfds ); // in addition to listening to the inbound sockets we // also listen to the asynchronous break pipe, so that AsynchronousBreak() // can break us out of select() from another thread. FD_SET( breakPipe_[0], &masterfds ); int fdmax = breakPipe_[0]; for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin(); i != socketListeners_.end(); ++i ){ if( fdmax < i->second->impl_->Socket() ) fdmax = i->second->impl_->Socket(); FD_SET( i->second->impl_->Socket(), &masterfds ); } // configure the timer queue double currentTimeMs = GetCurrentTimeMs(); // expiry time ms, listener std::vector< std::pair< double, AttachedTimerListener > > timerQueue_; for( std::vector< AttachedTimerListener >::iterator i = timerListeners_.begin(); i != timerListeners_.end(); ++i ) timerQueue_.push_back( std::make_pair( currentTimeMs + i->initialDelayMs, *i ) ); std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls ); const int MAX_BUFFER_SIZE = 4098; char *data = new char[ MAX_BUFFER_SIZE ]; IpEndpointName remoteEndpoint; struct timeval timeout; while( !break_ ){ tempfds = masterfds; struct timeval *timeoutPtr = 0; if( !timerQueue_.empty() ){ double timeoutMs = timerQueue_.front().first - GetCurrentTimeMs(); if( timeoutMs < 0 ) timeoutMs = 0; // 1000000 microseconds in a second timeout.tv_sec = (long)(timeoutMs * .001); timeout.tv_usec = (long)((timeoutMs - (timeout.tv_sec * 1000)) * 1000); timeoutPtr = &timeout; } if( select( fdmax + 1, &tempfds, 0, 0, timeoutPtr ) < 0 && errno != EINTR ){ throw std::runtime_error("select failed\n"); } if ( FD_ISSET( breakPipe_[0], &tempfds ) ){ // clear pending data from the asynchronous break pipe char c; if (read( breakPipe_[0], &c, 1 ) < 0) { fprintf(stderr, "Could not read from osc pipe.\n"); } } if( break_ ) break; for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin(); i != socketListeners_.end(); ++i ){ if( FD_ISSET( i->second->impl_->Socket(), &tempfds ) ){ int size = i->second->ReceiveFrom( remoteEndpoint, data, MAX_BUFFER_SIZE ); if( size > 0 ){ i->first->ProcessPacket( data, size, remoteEndpoint ); if( break_ ) break; } } } // execute any expired timers currentTimeMs = GetCurrentTimeMs(); bool resort = false; for( std::vector< std::pair< double, AttachedTimerListener > >::iterator i = timerQueue_.begin(); i != timerQueue_.end() && i->first <= currentTimeMs; ++i ){ i->second.listener->TimerExpired(); if( break_ ) break; i->first += i->second.periodMs; resort = true; } if( resort ) std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls ); } delete [] data; }
static void xmlrpc_handler(int fd) { fd_set rfds; struct timeval tv; int ret, len, max = 0, loadlen = -1; char buffer[CONFIG_EXAMPLES_XMLRPC_BUFFERSIZE] = { 0 }; char value[CONFIG_XMLRPC_STRINGSIZE + 1]; char *temp; /* Read in the Request Header */ do { FD_ZERO(&rfds); FD_SET(fd, &rfds); tv.tv_sec = 1; tv.tv_usec = 0; ndbg("[%d] select...\n", fd); ret = select(fd + 1, &rfds, NULL, NULL, &tv); ndbg("[%d] data ready\n", fd); if (ret > 0) { if (FD_ISSET(fd, &rfds)) { len = recv(fd, &buffer[max], 1024, 0); ndbg("[%d] %d bytes received\n", fd, len); if (len > 0) { max += len; buffer[max] = 0; ret = xmlrpc_getheader(buffer, "Content-Length:", value, CONFIG_EXAMPLES_XMLRPC_BUFFERSIZE); if (ret > 0) loadlen = atoi(value); } else { ret = -1; break; } } } else { /* Timeout... */ ndbg("[%d] timeout\n", fd); ret = -1; break; } temp = strstr(buffer, separator); if (temp) { if (strlen(temp) - 4 == loadlen) break; } } while (1); /* Determine request */ if (!strncmp(buffer, "POST", 4)) { temp = xmlrpc_findbody(buffer); xmlrpc_parse(fd, temp); } else { write(fd, notimplemented, strlen(notimplemented)); } }
bool KPtyDevicePrivate::doWait(int msecs, bool reading) { Q_Q(KPtyDevice); #ifndef __linux__ struct timeval etv; #endif struct timeval tv, *tvp; if (msecs < 0) tvp = nullptr; else { tv.tv_sec = msecs / 1000; tv.tv_usec = (msecs % 1000) * 1000; #ifndef __linux__ gettimeofday(&etv, 0); timeradd(&tv, &etv, &etv); #endif tvp = &tv; } while (reading ? readNotifier->isEnabled() : !writeBuffer.isEmpty()) { fd_set rfds; fd_set wfds; FD_ZERO(&rfds); FD_ZERO(&wfds); if (readNotifier->isEnabled()) FD_SET(q->masterFd(), &rfds); if (!writeBuffer.isEmpty()) FD_SET(q->masterFd(), &wfds); #ifndef __linux__ if (tvp) { gettimeofday(&tv, 0); timersub(&etv, &tv, &tv); if (tv.tv_sec < 0) tv.tv_sec = tv.tv_usec = 0; } #endif switch (select(q->masterFd() + 1, &rfds, &wfds, nullptr, tvp)) { case -1: if (errno == EINTR) break; return false; case 0: q->setErrorString(QLatin1String("PTY operation timed out")); return false; default: if (FD_ISSET(q->masterFd(), &rfds)) { bool canRead = _k_canRead(); if (reading && canRead) return true; } if (FD_ISSET(q->masterFd(), &wfds)) { bool canWrite = _k_canWrite(); if (!reading) return canWrite; } break; } } return false; }
/// 小数据量的收发,集中在一个线程里,不影响效率 void CTcpSock::P_ThreadWork() { byte bytLvl = 0; char szBuf[100] = {0}; DWORD dwLen = 0; DWORD dwPushTm; DWORD dwBufSize = (DWORD)sizeof(szBuf); bool bMustConn = false; int iFlag; int iret; int iConnFailTimes = 0; // 连续连接失败次数 static DWORD sta_dwLastConTm = GetTickCount(); fd_set rset, wset, eset; struct timeval tval; int iRecvLen; char szRecvbuf[ TCP_RECVSIZE+1 ]; char szSendBuf[ TCP_SENDSIZE ] = {0}; DWORD dwSendLen; //DWORD dwPushTm = 0; //BYTE bytLvl; szRecvbuf[0] = 0x00; // 0x00 表示中心TCP协议帧 DWORD dwSleep = 500; // ms while(!g_bProgExit) { usleep(dwSleep * 1000); dwSleep = 500; if( 0 == m_objSockStaMng.PopData(bytLvl, dwBufSize, dwLen, szBuf, dwPushTm) ) { switch(szBuf[0]) { case 0x01: { iConnFailTimes = 0; m_bytSockSta = DisConn; bMustConn = true; } break; default: break; } } switch( m_bytSockSta ) { case Idle: { // 若处于空闲状态,则每隔60秒连接一次中心 if( GetTickCount() - sta_dwLastConTm >= 60000 ) { m_bytSockSta = Conn; break; } if( bMustConn == true ) { m_bytSockSta = Conn; bMustConn = false; break; } } break; case Conn: { sta_dwLastConTm = GetTickCount(); // 若没有可用的临时IP,说明要连接到登陆服务器,此时则使用配置区中的IP if( m_dwSymb == DEV_DVR ) { for(int i=0; i<m_iIPCnt; i++) { if( m_bIPEnabled[i] ) { m_bIPEnabled[i] = false; // 使用一次后即置为假 m_conn.sin_family = AF_INET; m_conn.sin_port = m_usTempTcpPort[i]; m_conn.sin_addr.s_addr = m_ulTempIP[i]; // 且DVR UDP的地址和端口也要相应更改 g_objDvrUdp.m_ulIp = m_ulTempIP[i]; g_objDvrUdp.m_usPort = m_usTempUdpPort[i]; tag1QIpCfg obj1QIpCfg; GetImpCfg( &obj1QIpCfg, sizeof(obj1QIpCfg), offsetof(tagImportantCfg, m_uni1QComuCfg.m_ary1QIpCfg[0]), sizeof(obj1QIpCfg) ); obj1QIpCfg.m_ulVUdpIP = g_objDvrUdp.m_ulIp; obj1QIpCfg.m_usVUdpPort = g_objDvrUdp.m_usPort; SetImpCfg( &obj1QIpCfg, offsetof(tagImportantCfg, m_uni1QComuCfg.m_ary1QIpCfg[0]), sizeof(obj1QIpCfg) ); goto TCP_CONNECT; } } } // 读取IP、端口配置 tag1QIpCfg obj1QIpCfg[2]; tag1PComuCfg obj1PComuCfg; tag1LComuCfg obj1LComuCfg; if( GetImpCfg( (void*)&obj1QIpCfg, sizeof(obj1QIpCfg), offsetof(tagImportantCfg, m_uni1QComuCfg.m_ary1QIpCfg), sizeof(obj1QIpCfg) ) || GetImpCfg( (void*)&obj1PComuCfg, sizeof(obj1PComuCfg), offsetof(tagImportantCfg, m_uni1PComuCfg.m_obj1PComuCfg), sizeof(obj1PComuCfg) ) || GetImpCfg( (void*)&obj1LComuCfg, sizeof(obj1LComuCfg), offsetof(tagImportantCfg, m_uni1LComuCfg.m_obj1LComuCfg), sizeof(obj1LComuCfg) ) ) { PRTMSG(MSG_ERR, "Read IP Cfg Fail\n" ); m_bytSockSta = Idle; break; } m_conn.sin_family = AF_INET; switch( m_dwSymb ) { case DEV_QIAN: // king中心 { m_conn.sin_port = obj1QIpCfg[0].m_usQianTcpPort; m_conn.sin_addr.s_addr = obj1QIpCfg[0].m_ulQianTcpIP; } break; case DEV_DVR: // 独立视频服务器 { m_conn.sin_port = obj1QIpCfg[1].m_usQianTcpPort; m_conn.sin_addr.s_addr = obj1QIpCfg[1].m_ulQianTcpIP; } break; case DEV_UPDATE: // 管理平台 (应该增加一个新的标记,待) { m_conn.sin_port = obj1LComuCfg.m_usLiuPort2; m_conn.sin_addr.s_addr = obj1LComuCfg.m_ulLiuIP2; } break; default: break; } TCP_CONNECT: // 若配置为空,则返回 if( 0 == m_conn.sin_addr.s_addr || 0 == m_conn.sin_port || 0 == strcmp(obj1PComuCfg.m_szTel, "")) { PRTMSG(MSG_ERR, "IP/Port/Tel Cfg Is Uncompleted!\n"); G_RecordDebugInfo("IP/Port/Tel Cfg Is Uncompleted!\n"); m_bytSockSta = Idle; break; } // 确认关闭已有连接 if( -1 != m_sockTcp ) { shutdown(m_sockTcp, 2); close(m_sockTcp); m_sockTcp = -1; } m_sockTcp = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); if( -1 == m_sockTcp ) { PRTMSG(MSG_ERR, "Socket err\n" ); break; } bzero(&(m_conn.sin_zero),8); // 获取当前socket的属性, 并设置noblocking属性 iFlag = fcntl(m_sockTcp, F_GETFL, 0); fcntl(m_sockTcp, F_SETFL, iFlag | O_NONBLOCK); LINGER ling; ling.l_onoff = 1; // closesocket时强制关闭并立即释放套接字资源 ling.l_linger = 0; ::setsockopt( m_sockTcp, SOL_SOCKET, SO_LINGER, (char*)&ling, sizeof(ling) ); BOOL blVal = TRUE; // 禁止Nagle算法 setsockopt( m_sockTcp, IPPROTO_TCP, TCP_NODELAY, (char*)&blVal, sizeof(blVal) ); if( DEV_QIAN == m_dwSymb ) { PRTMSG(MSG_DBG, "Qian Tcp connect: Tel: %s, IP: %s, Port: %d\n", obj1PComuCfg.m_szTel, inet_ntoa(m_conn.sin_addr), htons(m_conn.sin_port)); RenewMemInfo(0x02, 0x02, 0x01, 0x03); G_RecordDebugInfo("Qian Tcp connect: Tel: %s, IP: %s, Port: %d", obj1PComuCfg.m_szTel, inet_ntoa(m_conn.sin_addr), htons(m_conn.sin_port)); } if(DEV_DVR == m_dwSymb) { PRTMSG(MSG_DBG, "Dvr Tcp connect: Tel: %s, IP: %s, Port: %d\n", obj1PComuCfg.m_szTel, inet_ntoa(m_conn.sin_addr), htons(m_conn.sin_port)); G_RecordDebugInfo("Dvr Tcp connect: Tel: %s, IP: %s, Port: %d", obj1PComuCfg.m_szTel, inet_ntoa(m_conn.sin_addr), htons(m_conn.sin_port)); } if( (iret = connect( m_sockTcp, (struct sockaddr *)&m_conn, sizeof(struct sockaddr))) < 0 ) { if(errno != EINPROGRESS) { PRTMSG(MSG_DBG, "connect failed, errno=%d\n", errno); G_RecordDebugInfo("connect failed, errno=%d", errno); perror(""); iConnFailTimes++; if( !_JudgeConFailMaxTime(iConnFailTimes) ) { sta_dwLastConTm = GetTickCount() - 57000; // 这样,3秒后可以尝试重新connect,提高效率 } m_bytSockSta = Idle; break; } } m_bytSockSta = WaitConn; } break; case WaitConn: { FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&eset); FD_SET(m_sockTcp, &rset); FD_SET(m_sockTcp, &wset); FD_SET(m_sockTcp, &eset); tval.tv_sec = 30; tval.tv_usec = 0; iret = select(m_sockTcp+1, &rset, &wset, &eset, &tval); if( 0 == iret ) { if( m_dwSymb == DEV_QIAN ) { PRTMSG(MSG_NOR, "Qian Tcp Socket connect time out!\n"); G_RecordDebugInfo("Tcp Socket connect time out!"); } if( m_dwSymb == DEV_DVR ) { PRTMSG(MSG_NOR, "Dvr Tcp Socket connect time out!\n"); G_RecordDebugInfo("Dvr Tcp Socket connect time out!"); } goto _CUR_CONNECT_FAIL; } else if(iret < 0) { PRTMSG(MSG_NOR, "Tcp Socket select err!\n"); goto _CUR_CONNECT_FAIL; } else { if( FD_ISSET(m_sockTcp, &eset) ) { PRTMSG(MSG_NOR, "Tcp Socket connect except!\n"); goto _CUR_CONNECT_FAIL; } else if(FD_ISSET(m_sockTcp, &rset) || FD_ISSET(m_sockTcp, &wset)) { m_bConnect = true; iConnFailTimes = 0; if( m_dwSymb == DEV_QIAN ) { PRTMSG(MSG_NOR, "Qian Tcp Socket Connect succ!\n"); G_RecordDebugInfo("Qian Tcp Socket Connect succ!"); } if( m_dwSymb == DEV_DVR ) { PRTMSG(MSG_NOR, "Dvr Socket Connect succ!\n"); G_RecordDebugInfo("Dvr Tcp Socket Connect succ!"); } if(m_dwSymb == DEV_DVR) { for(int i=0; i<MAX_TEMP_IP_CNT; i++) m_bIPEnabled[i] = false; } // 通知连接成功 char szbuf[2]; szbuf[0] = 0x01; // 0x01 表示非中心协议帧 szbuf[1] = 0x01; // 0x01 表示TCP套接字连接成功 DataPush((void*)szbuf, 2, DEV_SOCK, m_dwSymb, LV3); RenewMemInfo(0x02, 0x01, 0x01, 0x01); m_bytSockSta = Working; break; } else { PRTMSG(MSG_ERR, "Tcp Socket select err: sockfd not set\n" ); goto _CUR_CONNECT_FAIL; } } break; _CUR_CONNECT_FAIL: close(m_sockTcp); m_sockTcp = -1; iConnFailTimes++; if( !_JudgeConFailMaxTime(iConnFailTimes) ) { sta_dwLastConTm = GetTickCount() - 57000; // 这样,3秒后可以尝试重新connect,提高效率 } m_bytSockSta = DisConn; } break; case Working: { /// 先写 FD_ZERO(&wset); FD_ZERO(&eset); FD_SET(m_sockTcp, &wset); FD_SET(m_sockTcp, &eset); tval.tv_sec = 0; tval.tv_usec = 0; iret = select(m_sockTcp+1, NULL, &wset, &eset, &tval); if( iret > 0 ) { if( FD_ISSET(m_sockTcp, &eset) ) { PRTMSG(MSG_NOR, "Tcp Socket select write except!\n"); G_RecordDebugInfo("Tcp Socket select write except!"); goto _CUR_SOCK_EXCEPT; } else if( FD_ISSET(m_sockTcp, &wset) ) { if( 0 == m_objSendMng.PopData( bytLvl, sizeof(szSendBuf), dwSendLen, szSendBuf, dwPushTm) ) { if( dwSendLen > 0 && dwSendLen <= sizeof(szSendBuf) && -1 != m_sockTcp ) { iret = send( m_sockTcp, szSendBuf, dwSendLen, 0 ); if( iret > 0 ) { if( DEV_QIAN == m_dwSymb ) { PRTMSG(MSG_DBG, "Qian TcpSock send:"); } if( DEV_DVR == m_dwSymb ) { PRTMSG(MSG_DBG, "Dvr TcpSock send:"); } PrintString(szSendBuf,iret); } else if( iret < 0 ) { goto _CUR_SOCK_EXCEPT; } } dwSleep = 50; } } else { goto _CUR_SOCK_EXCEPT; } } else if( 0 == iret ) { PRTMSG(MSG_NOR, "Tcp Socket select write block!\n"); G_RecordDebugInfo("Tcp Socket select write block!"); } else if(iret < 0) { PRTMSG(MSG_NOR, "Tcp Socket select write err!\n"); G_RecordDebugInfo("Tcp Socket select write err!"); goto _CUR_SOCK_EXCEPT; } /// 后读 FD_ZERO(&rset); FD_ZERO(&eset); FD_SET(m_sockTcp, &rset); FD_SET(m_sockTcp, &eset); tval.tv_sec = 0; tval.tv_usec = 0; iret = select(m_sockTcp+1, &rset, NULL, &eset, &tval); if( iret > 0 ) { if( FD_ISSET(m_sockTcp, &eset) ) { PRTMSG(MSG_NOR, "Tcp Socket select read except!\n"); G_RecordDebugInfo("Tcp Socket select read except!"); goto _CUR_SOCK_EXCEPT; } else if( FD_ISSET(m_sockTcp, &rset) ) { iRecvLen = recv( m_sockTcp, szRecvbuf+1, sizeof(szRecvbuf)-1, 0 ); if( iRecvLen > 0 ) { if( DEV_QIAN == m_dwSymb ) { PRTMSG(MSG_NOR, "Qian Rcv Tcp Msg: "); } if( DEV_DVR == m_dwSymb ) { PRTMSG(MSG_NOR, "Dvr Rcv Tcp Msg: "); } PrintString(szRecvbuf+1, iRecvLen); DataPush(szRecvbuf, iRecvLen+1, DEV_SOCK, m_dwSymb, LV2); dwSleep = 50; } else { if(m_dwSymb == DEV_DVR) { PRTMSG(MSG_ERR, "Dvr Tcp socket recv err!\n"); G_RecordDebugInfo("Dvr Tcp socket recv err, errno=%d", errno); } if(m_dwSymb == DEV_QIAN) { PRTMSG(MSG_ERR, "Qian Tcp socket recv err!\n"); G_RecordDebugInfo("Qian Tcp socket recv err, errno=%d", errno); } perror(""); goto _CUR_SOCK_EXCEPT; } } } else if( iret < 0 ) { PRTMSG(MSG_ERR, "Tcp socket select err!\n"); G_RecordDebugInfo("Tcp socket select err!"); perror(""); goto _CUR_SOCK_EXCEPT; } break; _CUR_SOCK_EXCEPT: sta_dwLastConTm = GetTickCount() - 57000; // 这样,3秒后可以尝试重新connect,提高效率 m_bytSockSta = DisConn; } break; case DisConn: { if( m_dwSymb == DEV_QIAN ) G_RecordDebugInfo("Qian Tcp socket Disconn!"); if( m_dwSymb == DEV_DVR ) G_RecordDebugInfo("Dvr Tcp socket Disconn!"); if(m_sockTcp > 0) { shutdown(m_sockTcp, 2); close(m_sockTcp); m_sockTcp = -1; } // Tcp断开连接,则把Udp也断开 if( DEV_QIAN == m_dwSymb ) { g_objQianUdp.ReqDestroySock(); } if( DEV_DVR == m_dwSymb ) { g_objDvrUdp.ReqDestroySock(); } // 通知断开连接 char szbuf[2]; szbuf[0] = 0x01; // 0x01 表示非中心协议帧 szbuf[1] = 0x02; // 0x02 表示通知网络断开连接 DataPush((void*)szbuf, 2, DEV_SOCK, m_dwSymb, LV3); RenewMemInfo(0x02, 0x01, 0x01, 0x00); m_bytSockSta = Idle; } break; default: { m_bytSockSta = Idle; } break; } } }
static void connectServer(const char *stty, const char *dev) { int fdmax, newfd; fd_set master, read_fds; FD_ZERO(&master); FD_ZERO(&read_fds); int serverfd; serverfd = createServerSocket(dev); if (serverfd < 0) { syslog(LOG_ERR, "mTerm_server: Failed to create server socket\n"); return; } struct ttyRaw* tty_sol; tty_sol = setTty(openTty(stty), 1); if (!tty_sol) { syslog(LOG_ERR, "mTerm_server: Failed to set tty to raw mode\n"); close(serverfd); return; } struct bufStore* buf; buf = createBuffer(dev, FILE_SIZE_BYTES); if (!buf || (buf->buf_fd < 0)) { syslog(LOG_ERR, "mTerm_server: Failed to create the log file\n"); closeTty(tty_sol); close(serverfd); return; } FD_SET(serverfd, &master); FD_SET(tty_sol->fd,&master); fdmax = (serverfd > tty_sol->fd) ? serverfd : tty_sol->fd; for(;;) { read_fds = master; if (select(fdmax + 1, &read_fds, NULL, NULL, NULL) == -1) { syslog(LOG_ERR, "mTerm_server: Server socket: select error\n"); break; } if (FD_ISSET(serverfd, &read_fds)) { newfd = acceptClient(serverfd); if (newfd < 0) { syslog(LOG_ERR, "mTerm_server: Error on accepting client\n"); } else { FD_SET(newfd, &master); if (newfd > fdmax) { fdmax = newfd; } } } if (FD_ISSET(tty_sol->fd, &read_fds)) { if ( processSol(&master, serverfd, fdmax, tty_sol->fd, buf) < 0) { break; } } int i; for(i = 0; i <= fdmax; i++) { if (FD_ISSET(i, &read_fds)) { if ((i == serverfd) || (i == tty_sol->fd)) { continue; } else { processClient(&master, i, tty_sol->fd, buf); } } } } closeTty(tty_sol); close(serverfd); closeBuffer(buf); }
void interconnect_stream (FILE *sock_in, FILE *sock_out, int sock_fd) { /* 具体的には、以下の挙動をすれば良いと思われる。 * - selectを使って、stdin(STDIN_FILENO)とソケットのどちらかから * データが読み取れる状態になるのを待つ。 * -- stdin(STDIN_FILENO)が読み出しokになったら、 * 読み出せる限り読み出して、それをソケットに書き出す。 * -- ソケットが読み出しokになったら、 * 読み出せる限り読み出して、それをstdoutに書き出す。 * -- どちらかがEOFまたは何からのエラーが来たら、それに応じた終了処理を行う */ /* sigmaskを生成する * ……が、前提として、予めSIGPIPEは無視してある、という事にする。 * ここでは省略する。 */ /* SIGPIPEを無視する事については以下を参照 * http://www.kt.rim.or.jp/~ksk/sock-faq/unix-socket-faq-ja-2.html#ss2.19 */ /* stdinのEOFはフラグ管理する必要がある */ char stdin_is_eof = 0; while (1) { /* nfdsを生成する */ int nfds; if (stdin_is_eof) { nfds = sock_fd + 1; } else { nfds = ((STDIN_FILENO < sock_fd) ? sock_fd : STDIN_FILENO) + 1; } /* fd_setを生成する */ fd_set readfds; FD_ZERO(&readfds); if (!stdin_is_eof) FD_SET(STDIN_FILENO, &readfds); FD_SET(sock_fd, &readfds); /* timevalを生成する(man 2 selectによると、 * select時にtimeoutが破壊される環境があるらしいので毎回生成する) */ struct timeval timeout; timeout.tv_sec = SELECT_TIMEOUT; /* 秒 */ timeout.tv_usec = 0; /* マイクロ秒 */ /* selectを実行する */ int r = select(nfds, &readfds, NULL, NULL, &timeout); if (r == -1) { if (errno == EINTR) { /* シグナルを受信した */ /* とりあえず終了でいいと思う */ perror("caught a signal"); break; } else { /* よく分からないエラー */ /* エラー内容をstderrに書き出す必要がある */ perror("unknown error in select"); break; } } if (!FD_ISSET(sock_fd, &readfds) && (stdin_is_eof || !FD_ISSET(STDIN_FILENO, &readfds))) { /* エラーでもないし、読み取り可能にもなってない状況なら、 * タイムアウトしたものと考えられる。 * (本来ならcontinue等を使って分かりやすい構造にしたいが、 * ソケットとstdinが同時の読み取り可能になった時に、 * 片方に偏らせたくないので、 * 一回のselectで両方とも処理可能にする為に、 * こんなややっこしい構造になってしまった) * 尚、この処理は、下のstdin確認よりも先にチェックする必要がある。 * (stdin確認の内部でstdin_is_eofフラグを変更している為) */ fprintf(stderr, "socket response timeout\n"); break; } if (FD_ISSET(sock_fd, &readfds)) { /* ソケットから読み取り可能 */ /* 適当に読み取り、読み取った分をstdoutに書き出す */ int r = stream_transfer(sock_in, stdout); if (r <= 0) { /* socketがEOFになったら、stdoutのcloseを行う * (実際には不要だが、一応しておく) */ fclose(stdout); break; /* ソケットがEOFになったら即終了 */ } } if (!stdin_is_eof && FD_ISSET(STDIN_FILENO, &readfds)) { /* stdinから読み取り可能 */ /* 適当に読み取り、読み取った分をソケットに書き出す */ int r = stream_transfer(stdin, sock_out); if (r <= 0) { /* stdinがEOFになったら、sock_outのshutdownを行う * (closeするとreadの方までcloseされてしまうので、closeはしない) */ fflush(sock_out); shutdown(sock_fd, SHUT_WR); stdin_is_eof = 1; /* stdinがEOFになっても即終了しない */ } } } return; }
int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { int i; /* Looping var */ ipp_t *event; /* Event from scheduler */ ipp_state_t state; /* IPP event state */ char scheme[32], /* URI scheme ("rss") */ username[256], /* Username for remote RSS */ host[1024], /* Hostname for remote RSS */ resource[1024], /* RSS file */ *options; /* Options */ int port, /* Port number for remote RSS */ max_events; /* Maximum number of events */ http_t *http; /* Connection to remote server */ http_status_t status; /* HTTP GET/PUT status code */ char filename[1024], /* Local filename */ newname[1024]; /* filename.N */ cups_lang_t *language; /* Language information */ ipp_attribute_t *printer_up_time, /* Timestamp on event */ *notify_sequence_number,/* Sequence number */ *notify_printer_uri; /* Printer URI */ char *subject, /* Subject for notification message */ *text, /* Text for notification message */ link_url[1024], /* Link to printer */ link_scheme[32], /* Scheme for link */ link_username[256], /* Username for link */ link_host[1024], /* Host for link */ link_resource[1024]; /* Resource for link */ int link_port; /* Link port */ cups_array_t *rss; /* RSS message array */ _cups_rss_t *msg; /* RSS message */ char baseurl[1024]; /* Base URL */ fd_set input; /* Input set for select() */ struct timeval timeout; /* Timeout for select() */ int changed; /* Has the RSS data changed? */ int exit_status; /* Exit status */ fprintf(stderr, "DEBUG: argc=%d\n", argc); for (i = 0; i < argc; i ++) fprintf(stderr, "DEBUG: argv[%d]=\"%s\"\n", i, argv[i]); /* * See whether we are publishing this RSS feed locally or remotely... */ if (httpSeparateURI(HTTP_URI_CODING_ALL, argv[1], scheme, sizeof(scheme), username, sizeof(username), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_OK) { fprintf(stderr, "ERROR: Bad RSS URI \"%s\"!\n", argv[1]); return (1); } max_events = 20; if ((options = strchr(resource, '?')) != NULL) { *options++ = '\0'; if (!strncmp(options, "max_events=", 11)) { max_events = atoi(options + 11); if (max_events <= 0) max_events = 20; } } rss = cupsArrayNew((cups_array_func_t)compare_rss, NULL); if (host[0]) { /* * Remote feed, see if we can get the current file... */ int fd; /* Temporary file */ if ((rss_password = strchr(username, ':')) != NULL) *rss_password++ = '\0'; cupsSetPasswordCB(password_cb); cupsSetUser(username); if ((fd = cupsTempFd(filename, sizeof(filename))) < 0) { fprintf(stderr, "ERROR: Unable to create temporary file: %s\n", strerror(errno)); return (1); } if ((http = httpConnect(host, port)) == NULL) { fprintf(stderr, "ERROR: Unable to connect to %s on port %d: %s\n", host, port, strerror(errno)); close(fd); unlink(filename); return (1); } status = cupsGetFd(http, resource, fd); close(fd); if (status != HTTP_OK && status != HTTP_NOT_FOUND) { fprintf(stderr, "ERROR: Unable to GET %s from %s on port %d: %d %s\n", resource, host, port, status, httpStatus(status)); httpClose(http); unlink(filename); return (1); } strlcpy(newname, filename, sizeof(newname)); httpAssembleURI(HTTP_URI_CODING_ALL, baseurl, sizeof(baseurl), "http", NULL, host, port, resource); } else { const char *cachedir, /* CUPS_CACHEDIR */ *server_name, /* SERVER_NAME */ *server_port; /* SERVER_PORT */ http = NULL; if ((cachedir = getenv("CUPS_CACHEDIR")) == NULL) cachedir = CUPS_CACHEDIR; if ((server_name = getenv("SERVER_NAME")) == NULL) server_name = "localhost"; if ((server_port = getenv("SERVER_PORT")) == NULL) server_port = "631"; snprintf(filename, sizeof(filename), "%s/rss%s", cachedir, resource); snprintf(newname, sizeof(newname), "%s.N", filename); httpAssembleURIf(HTTP_URI_CODING_ALL, baseurl, sizeof(baseurl), "http", NULL, server_name, atoi(server_port), "/rss%s", resource); } /* * Load the previous RSS file, if any... */ load_rss(rss, filename); changed = cupsArrayCount(rss) == 0; /* * Localize for the user's chosen language... */ language = cupsLangDefault(); /* * Read events and update the RSS file until we are out of events. */ for (exit_status = 0, event = NULL;;) { if (changed) { /* * Save the messages to the file again, uploading as needed... */ if (save_rss(rss, newname, baseurl)) { if (http) { /* * Upload the RSS file... */ if ((status = cupsPutFile(http, resource, filename)) != HTTP_CREATED) fprintf(stderr, "ERROR: Unable to PUT %s from %s on port %d: %d %s\n", resource, host, port, status, httpStatus(status)); } else { /* * Move the new RSS file over top the old one... */ if (rename(newname, filename)) fprintf(stderr, "ERROR: Unable to rename %s to %s: %s\n", newname, filename, strerror(errno)); } changed = 0; } } /* * Wait up to 30 seconds for an event... */ timeout.tv_sec = 30; timeout.tv_usec = 0; FD_ZERO(&input); FD_SET(0, &input); if (select(1, &input, NULL, NULL, &timeout) < 0) continue; else if (!FD_ISSET(0, &input)) { fprintf(stderr, "DEBUG: %s is bored, exiting...\n", argv[1]); break; } /* * Read the next event... */ event = ippNew(); while ((state = ippReadFile(0, event)) != IPP_DATA) { if (state <= IPP_IDLE) break; } if (state == IPP_ERROR) fputs("DEBUG: ippReadFile() returned IPP_ERROR!\n", stderr); if (state <= IPP_IDLE) break; /* * Collect the info from the event... */ printer_up_time = ippFindAttribute(event, "printer-up-time", IPP_TAG_INTEGER); notify_sequence_number = ippFindAttribute(event, "notify-sequence-number", IPP_TAG_INTEGER); notify_printer_uri = ippFindAttribute(event, "notify-printer-uri", IPP_TAG_URI); subject = cupsNotifySubject(language, event); text = cupsNotifyText(language, event); if (printer_up_time && notify_sequence_number && subject && text) { /* * Create a new RSS message... */ if (notify_printer_uri) { httpSeparateURI(HTTP_URI_CODING_ALL, notify_printer_uri->values[0].string.text, link_scheme, sizeof(link_scheme), link_username, sizeof(link_username), link_host, sizeof(link_host), &link_port, link_resource, sizeof(link_resource)); httpAssembleURI(HTTP_URI_CODING_ALL, link_url, sizeof(link_url), "http", link_username, link_host, link_port, link_resource); } msg = new_message(notify_sequence_number->values[0].integer, xml_escape(subject), xml_escape(text), notify_printer_uri ? xml_escape(link_url) : NULL, printer_up_time->values[0].integer); if (!msg) { fprintf(stderr, "ERROR: Unable to create message: %s\n", strerror(errno)); exit_status = 1; break; } /* * Add it to the array... */ cupsArrayAdd(rss, msg); changed = 1; /* * Trim the array as needed... */ while (cupsArrayCount(rss) > max_events) { msg = cupsArrayFirst(rss); cupsArrayRemove(rss, msg); delete_message(msg); } } if (subject) free(subject); if (text) free(text); ippDelete(event); event = NULL; } /* * We only get here when idle or error... */ ippDelete(event); if (http) { unlink(filename); httpClose(http); } return (exit_status); }
int main(void) { RTPSession sess; int portbase; unsigned long destip; int destport; char ipstr[256]; int status; char dummybuffer[1024]; struct timeval rttprev = {0,0},rtt,tv; int sock1,sock2; bool done; fd_set fdset; /* First, we'll ask for the necessary information */ printf("Enter the local portbase\n"); scanf("%d",&portbase); printf("\n"); printf("Enter the destination IP address\n"); scanf("%s",ipstr); destip = inet_addr(ipstr); if (destip == INADDR_NONE) { printf("Bad IP address specified\n"); return -1; } // The inet_addr function returns a value in network byte order, but // we need the IP address in host byte order, so we use a call to // ntohl destip = ntohl(destip); printf("Enter the destination port\n"); scanf("%d",&destport); /* Now, we'll create a RTP session, set the destination, send some packets and poll for incoming data. */ status = sess.Create(portbase); checkerror(status); /* Get the sockets, so we can use them in a 'select' call */ sess.GetRTPSocket(&sock1); sess.GetRTCPSocket(&sock2); status = sess.AddDestination(destip,destport); checkerror(status); printf("Press return to quit...\n"); done = false; while (!done) { /* Just send something */ status = sess.SendPacket("1234567890",10,0,false,10); checkerror(status); /* Wait for incoming data, or wait just one second */ tv.tv_sec = 1; tv.tv_usec = 0; FD_ZERO(&fdset); FD_SET(sock1,&fdset); FD_SET(sock2,&fdset); FD_SET(0,&fdset); // check for keypress select(FD_SETSIZE,&fdset,NULL,NULL,&tv); if (FD_ISSET(0,&fdset)) done = true; /* poll for incoming data */ status = sess.PollData(); /* check incoming packets */ if (sess.GotoFirstSourceWithData()) { do { RTPSourceData *srcdat; srcdat = sess.GetCurrentSourceInfo(); srcdat->FlushPackets(); // we don't need the actual data rtt = srcdat->INF_GetRoundTripTime(); if (rtt.tv_sec != 0 || rtt.tv_usec != 0) { if ((rtt.tv_sec != rttprev.tv_sec) || (rtt.tv_usec != rttprev.tv_usec)) { double t; t = (double)rtt.tv_sec; t += ((double)rtt.tv_usec)/1000000.0; t *= 1000.0; // we want milliseconds; printf("rtt: %f ms\n",(float)t); rttprev = rtt; } } } while (sess.GotoNextSourceWithData()); } } return 0; }
/*-------------------------------------------------------------------------- ** Purpose: Check for network status. ** ** Parameters: Name Description. ** ** Returns: Nothing. ** **------------------------------------------------------------------------*/ void npuNetCheckStatus(void) { struct timeval timeout; int readySockets = 0; Tcb *tp; timeout.tv_sec = 0; timeout.tv_usec = 0; while (pollIndex < npuNetTelnetConns) { tp = npuTcbs + pollIndex++; if (tp->state == StTermIdle) { continue; } /* ** Handle transparent input timeout. */ if (tp->xInputTimerRunning && (cycles - tp->xStartCycle) >= Ms200) { npuAsyncFlushUplineTransparent(tp); } /* ** Handle network traffic. */ FD_ZERO(&readFds); FD_ZERO(&writeFds); FD_SET(tp->connFd, &readFds); FD_SET(tp->connFd, &writeFds); readySockets = select(tp->connFd + 1, &readFds, &writeFds, NULL, &timeout); if (readySockets <= 0) { continue; } if (npuBipQueueNotEmpty(&tp->outputQ) && FD_ISSET(tp->connFd, &writeFds)) { /* ** Send data if any is pending. */ npuNetTryOutput(tp); } if (FD_ISSET(tp->connFd, &readFds)) { /* ** Receive a block of data. */ tp->inputCount = recv(tp->connFd, tp->inputData, sizeof(tp->inputData), 0); if (tp->inputCount <= 0) { /* ** Received disconnect - close socket. */ #if defined(_WIN32) closesocket(tp->connFd); #else close(tp->connFd); #endif npuLogMessage("npuNet: Connection dropped on port %d\n", tp->portNumber); /* ** Notify SVM. */ npuSvmDiscRequestTerminal(tp); } else if (tp->state == StTermHostConnected) { /* ** Hand up to the ASYNC TIP. */ npuAsyncProcessUplineData(tp); } /* ** The following return ensures that we resume with polling the next ** connection in sequence otherwise low-numbered connections would get ** preferential treatment. */ return; } } pollIndex = 0; }
void gw_im_listener(void *arg) { fd_set in_pipes; int i,j; int host_id; int greater, rc, rcm; int num_mads; char c; char info[GW_IM_MAX_INFO]; char s_host_id[GW_IM_MAX_HOST_ID]; char result[GW_IM_MAX_RESULT]; char action[GW_IM_MAX_ACTION]; char str[GW_IM_MAX_STRING]; gw_host_t * host; gw_im_mad_t * im_mad; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); while (1) { greater = gw_im_set_pipes (&in_pipes, &num_mads); select(greater+1, &in_pipes, NULL, NULL, NULL); for (i=0; i<=greater; i++) { if ( FD_ISSET(i, &in_pipes) ) { im_mad = gw_im_get_mad_by_fd(i); if ( im_mad == NULL ) continue; j = 0; do { rc = read(i, (void *) &c, sizeof(char)); str[j++] = c; } while ((rc > 0) && (c != '\n') && (j < (GW_IM_MAX_STRING-1))); str[j] = '\0'; if (rc <= 0) { gw_log_print("IM",'W',"Error reading MAD (%s) message\n", im_mad->name); rcm = gw_im_mad_reload (im_mad); if ( rcm == 0 ) gw_log_print("IM",'I',"MAD (%s) successfully reloaded\n", im_mad->name); else { gw_log_print("IM",'E',"Error reloading IM MAD (%s)\n", im_mad->name); im_mad->mad_im_pipe = -1; if ( num_mads == 1 ) { gw_log_print("IM",'E',"GridWay needs to be restarted (no IM MADs left)!\n"); return; } } continue; } info[0] = '\0'; rc = sscanf(str,"%" GW2STR(GW_IM_MAX_ACTION)"s %" GW2STR(GW_IM_MAX_HOST_ID)"s %" GW2STR(GW_IM_MAX_RESULT)"s %" GW2STR(GW_IM_MAX_INFO) "[^\n]", action, s_host_id, result, info); #ifdef GWIMDEBUG gw_log_print("IM",'D',"MAD (%s) message %s %s %s %s (info length=%d).\n", im_mad->name, action, s_host_id, result, info, strlen(info)); #endif if ( rc < 3 ) { gw_log_print("IM",'E',"Wrong field number in MAD (%s) message: %s.\n", im_mad->name, str); continue; } if (s_host_id[0] != '-') { host_id = atoi(s_host_id); host = gw_host_pool_get_host (host_id, GW_FALSE); if (host == NULL) { gw_log_print("IM",'E',"Message %s for host %d (does not exist) from MAD (%s).\n", im_mad->name, action, host_id); continue; } } else { host_id = -1; } if (strcmp(action, "DISCOVER") == 0) { pthread_mutex_lock(&(gw_im.mutex)); gw_im.active_queries--; #ifdef GWIMDEBUG gw_log_print("IM",'D',"Discovery action done, %i active queries.\n", gw_im.active_queries); #endif pthread_mutex_unlock(&(gw_im.mutex)); if (strcmp(result, "SUCCESS") == 0) { if (strlen(info) > 0) { gw_log_print("IM",'I',"Hosts discovered by MAD (%s): %s\n", im_mad->name, info); gw_host_pool_update(info, im_mad->em_mad_name, im_mad->tm_mad_name, im_mad->name); #ifdef GWIMDEBUG gw_host_pool_print(stdout); #endif } else { gw_log_print("IM",'I',"No hosts discovered by MAD (%s)\n", im_mad->name); } } else { gw_log_print("IM",'E',"DISCOVER error in MAD (%s): %s\n", im_mad->name, info); } im_mad->state = GW_IM_MAD_STATE_IDLE; } else if (strcmp(action, "MONITOR") == 0) { pthread_mutex_lock(&(gw_im.mutex)); gw_im.active_queries--; #ifdef GWIMDEBUG gw_log_print("IM",'D',"Monitoring action done, %i active queries.\n", gw_im.active_queries); #endif pthread_mutex_unlock(&(gw_im.mutex)); if (strcmp(result, "SUCCESS") == 0) { gw_host_update(host_id, info); #ifdef GWIMDEBUG gw_log_print("IM",'D',"Host %i successfully monitored.\n", host_id); #endif } else { gw_log_print("IM",'E',"MONITOR error in MAD (%s): %s\n", im_mad->name, info); gw_host_clear_dynamic_info(host_id); } } } } } }
// // function: tunnel_server_handler // opne a service port and process the service request from devices // parameters // service port number // return // 0 success // other fail // void *tunnel_server_handler(void *pdata) { fd_set readfds, writefds, rfds, wfds; int nfds=-1,servfd=-1, sd=-1, ret=-1; struct timeval tv; struct sockaddr_in clientaddr; /* client addr */ int optval; /* service socket */ unsigned int next_time, current_time; #ifdef _OPEN_SECURED_CONN SSL *ssl=NULL; int securefd = -1; #endif // // tunnel control block init // if (tunnel_ctrl_init()<0) { p2p_log_msg( "initial tunnel control block fail!"); goto end_tunnel_server_handler; } FD_ZERO(&readfds); FD_ZERO(&writefds); // wait mone secure connection servfd = do_bind_service_port(service_port); if (servfd>=0) { FD_SET(servfd, &readfds); nfds = (servfd>nfds?servfd:nfds); } else goto end_tunnel_server_handler; #ifdef _OPEN_SECURED_CONN // wait mone secure connection securefd = do_bind_service_port(secure_service_port); if (securefd>=0) { FD_SET(securefd, &readfds); nfds = (securefd>nfds?securefd:nfds); } else goto end_tunnel_server_handler; #endif // // report to SC that service start // do_service_start("tunnel server start"); // // main loop: wait for a connection request // current_time = get_time_milisec(); next_time = current_time + 10000; // next seconds while (tunnel_server_on) { current_time = get_time_milisec(); if (current_time > next_time) { // if timer expired, do report to SC do_service_report(); next_time = current_time + 10000; // 10 seconds } memcpy(&rfds,&readfds,sizeof(fd_set)); memcpy(&wfds,&writefds,sizeof(fd_set)); // reset timeout value tv.tv_sec = 1; // 1 seconds tv.tv_usec = 0; if((ret=select(nfds+1, &rfds, &wfds, NULL, &tv)) == -1) { p2p_log_msg( "Server-select() error lol!"); goto end_tunnel_server_handler; } #ifdef _OPEN_SECURED_CONN if (FD_ISSET(securefd, &rfds)) { socklen_t clientlen = sizeof(clientaddr); sd = ssl_server_accept(securefd,&ssl); if (sd >= 0) { getpeername(sd, (struct sockaddr*)&clientaddr, &clientlen); p2p_log_msg("new secure connection from %s\n",inet_ntoa (clientaddr.sin_addr)); ret = new_device_tunnel(sd, &clientaddr, ssl); if (ret<0) { p2p_log_msg("reject secure connection from %s\n",inet_ntoa (clientaddr.sin_addr)); ssl_server_close(ssl); } } else p2p_log_msg("ERROR on accept"); } #endif // new conenction incoming? if (FD_ISSET(servfd, &rfds)) { // // accept: wait for a connection request // socklen_t clientlen = sizeof(clientaddr); sd = accept(servfd, (struct sockaddr *) &clientaddr, &clientlen); if (sd >= 0) { getpeername(sd, (struct sockaddr*)&clientaddr, &clientlen); p2p_log_msg("new connection from %s\n",inet_ntoa (clientaddr.sin_addr)); #ifdef _OPEN_SECURED_CONN ret = new_device_tunnel(sd, &clientaddr, NULL); #else ret = new_device_tunnel(sd, &clientaddr); #endif if (ret<0) { p2p_log_msg("reject connection from %s\n",inet_ntoa (clientaddr.sin_addr)); close(sd); } } else p2p_log_msg("ERROR on accept"); } } // end of while end_tunnel_server_handler: // close all existing tunnel if (servfd>0) close(servfd); #ifdef _OPEN_SECURED_CONN if (securefd>=0) close(securefd); #endif do_service_exit("tunnel server exit"); tunnel_ctrl_free(); tunnel_server_on = 0; return NULL; } // endo fo tunnel server