/* * Loop forever handling clients as they come and go. * Access to the framebuffer may be interleaved, if the user * wants it that way. */ static void main_loop(void) { int nopens = 0; int ncloses = 0; while ( !fb_server_got_fb_free ) { long refresh_rate = 60000000; /* old default */ fd_set infds; struct timeval tv; int i; if (fb_server_fbp) { if (fb_poll_rate(fb_server_fbp) > 0) refresh_rate = fb_poll_rate(fb_server_fbp); } infds = select_list; /* struct copy */ tv.tv_sec = 0L; tv.tv_usec = refresh_rate; if ((select( max_fd+1, &infds, (fd_set *)0, (fd_set *)0, (struct timeval *)&tv ) == 0)) { /* Process fb events while waiting for client */ /*printf("select timeout waiting for client\n");*/ if (fb_server_fbp) { if (fb_poll(fb_server_fbp)) { return; } } continue; } /* Handle any events from the framebuffer */ if (fb_is_set_fd(fb_server_fbp, &infds)) { fb_poll(fb_server_fbp); } /* Accept any new client connections */ if (netfd > 0 && FD_ISSET(netfd, &infds)) { new_client( pkg_getclient( netfd, fb_server_pkg_switch, comm_error, 0 ) ); nopens++; } /* Process arrivals from existing clients */ /* First, pull the data out of the kernel buffers */ for (i = MAX_CLIENTS-1; i >= 0; i--) { if (clients[i] == NULL ) continue; if (pkg_process( clients[i] ) < 0) { fprintf(stderr, "pkg_process error encountered (1)\n"); } if (! FD_ISSET( clients[i]->pkc_fd, &infds )) continue; if (pkg_suckin( clients[i] ) <= 0) { /* Probably EOF */ drop_client( i ); ncloses++; continue; } } /* Second, process all the finished ones that we just got */ for (i = MAX_CLIENTS-1; i >= 0; i--) { if (clients[i] == NULL ) continue; if (pkg_process( clients[i] ) < 0) { fprintf(stderr, "pkg_process error encountered (2)\n"); } } if (once_only && nopens > 1 && ncloses > 1) return; } }
int main(int argc, char **argv) { #define PORTSZ 32 char portname[PORTSZ]; max_fd = 0; /* No disk files on remote machine */ _fb_disk_enable = 0; memset((void *)clients, 0, sizeof(struct pkg_conn *) * MAX_CLIENTS); #ifdef SIGALRM (void)signal( SIGPIPE, SIG_IGN ); (void)signal( SIGALRM, sigalarm ); #endif /*alarm(1)*/ FD_ZERO(&select_list); fb_server_select_list = &select_list; fb_server_max_fd = &max_fd; #ifndef _WIN32 /* * Inetd Daemon. * Check to see if we were invoked by /etc/inetd. If so * we will have an open network socket on fd=0. Become * a Transient PKG server if this is so. */ netfd = 0; if ( is_socket(netfd) ) { init_syslog(); new_client( pkg_transerver( fb_server_pkg_switch, comm_error ) ); max_fd = 8; once_only = 1; main_loop(); return 0; } #endif /* for now, make them set a port_num, for usage message */ if ( !get_args( argc, argv ) || !port_set ) { (void)fputs(usage, stderr); return 1; } /* Single-Frame-Buffer Server */ if ( framebuffer != NULL ) { fb_server_retain_on_close = 1; /* don't ever close the frame buffer */ /* open a frame buffer */ if ( (fb_server_fbp = fb_open(framebuffer, width, height)) == FB_NULL ) bu_exit(1, NULL); max_fd = fb_set_fd(fb_server_fbp, &select_list); /* check/default port */ if ( port_set ) { if ( port < 1024 ) port += 5559; } snprintf(portname, PORTSZ, "%d", port); /* * Hang an unending listen for PKG connections */ if ( (netfd = pkg_permserver(portname, 0, 0, comm_error)) < 0 ) bu_exit(-1, NULL); FD_SET(netfd, &select_list); V_MAX(max_fd, netfd); main_loop(); return 0; } #ifndef _WIN32 /* * Stand-Alone Daemon */ /* check/default port */ if ( port_set ) { if ( port < 1024 ) port += 5559; sprintf(portname, "%d", port); } else { snprintf(portname, PORTSZ, "%s", "remotefb"); } init_syslog(); while ( (netfd = pkg_permserver(portname, 0, 0, comm_error)) < 0 ) { static int error_count=0; sleep(1); if (error_count++ < 60) { continue; } comm_error("Unable to start the stand-alone framebuffer daemon after 60 seconds, giving up."); return 1; } while (1) { int fbstat; struct pkg_conn *pcp; pcp = pkg_getclient( netfd, fb_server_pkg_switch, comm_error, 0 ); if ( pcp == PKC_ERROR ) break; /* continue is unlikely to work */ if ( fork() == 0 ) { /* 1st level child process */ (void)close(netfd); /* Child is not listener */ /* Create 2nd level child process, "double detach" */ if ( fork() == 0 ) { /* 2nd level child -- start work! */ new_client( pcp ); once_only = 1; main_loop(); return 0; } else { /* 1st level child -- vanish */ return 1; } } else { /* Parent: lingering server daemon */ pkg_close(pcp); /* Daemon is not the server */ /* Collect status from 1st level child */ (void)wait( &fbstat ); } } #endif /* _WIN32 */ return 2; }
/** * start up a server that listens for a single client. */ void run_server(int port) { struct pkg_conn *client; int netfd; char portname[MAX_DIGITS + 1] = {0}; /* int pkg_result = 0; */ char *buffer, *msgbuffer; long bytes = 0; FILE *fp; /** our server callbacks for each message type */ struct pkg_switch callbacks[] = { {MSG_HELO, server_helo, "HELO", NULL}, {MSG_DATA, server_data, "DATA", NULL}, {MSG_CIAO, server_ciao, "CIAO", NULL}, {0, 0, (char *)0, (void*)0} }; validate_port(port); /* start up the server on the given port */ snprintf(portname, MAX_DIGITS, "%d", port); netfd = pkg_permserver(portname, "tcp", 0, 0); if (netfd < 0) { bu_bomb("Unable to start the server"); } /* listen for a good client indefinitely. this is a simple * handshake that waits for a HELO message from the client. if it * doesn't get one, the server continues to wait. */ do { client = pkg_getclient(netfd, callbacks, NULL, 0); if (client == PKC_NULL) { bu_log("Connection seems to be busy, waiting...\n"); sleep(10); continue; } else if (client == PKC_ERROR) { bu_log("Fatal error accepting client connection.\n"); pkg_close(client); client = PKC_NULL; continue; } /* got a connection, process it */ msgbuffer = pkg_bwaitfor (MSG_HELO, client); if (msgbuffer == NULL) { bu_log("Failed to process the client connection, still waiting\n"); pkg_close(client); client = PKC_NULL; } else { bu_log("msgbuffer: %s\n", msgbuffer); /* validate magic header that client should have sent */ if (!BU_STR_EQUAL(msgbuffer, MAGIC_ID)) { bu_log("Bizarre corruption, received a HELO without at matching MAGIC ID!\n"); pkg_close(client); client = PKC_NULL; } } } while (client == PKC_NULL); /* have client, will send file */ fp = fopen("lempar.c", "rb"); buffer = (char *)bu_calloc(2048, 1, "buffer allocation"); if (fp == NULL) { bu_log("Unable to open lempar.c\n"); bu_bomb("Unable to read file\n"); } /* send the file data to the server */ while (!feof(fp) && !ferror(fp)) { bytes = fread(buffer, 1, 2048, fp); bu_log("Read %ld bytes from lempar.c\n", bytes); if (bytes > 0) { bytes = pkg_send(MSG_DATA, buffer, (size_t)bytes, client); if (bytes < 0) { pkg_close(client); bu_log("Unable to successfully send data"); bu_free(buffer, "buffer release"); return; } } } /* Tell the client we're done */ bytes = pkg_send(MSG_CIAO, "DONE", 5, client); if (bytes < 0) { bu_log("Connection to client seems faulty.\n"); } /* Confirm the client is done */ buffer = pkg_bwaitfor (MSG_CIAO , client); bu_log("buffer: %s\n", buffer); /* shut down the server, one-time use */ pkg_close(client); }