void IghtConnectionState::handle_read(bufferevent *bev, void *opaque) { auto self = (IghtConnectionState *) opaque; (void) bev; // Suppress warning about unused variable self->reading = 1; self->on_data(bufferevent_get_input(self->bev)); self->reading = 0; if (self->closing) delete (self); }
void Parser::parse( const char *str, int len, bool end ) { const char *p = str; const char *pos = p; const char *s = 0;//数据开始位置 const char *e = 0;//数据结束位置 while( len > 0 ) { if( *p == '<' ) { pos = p; if( s ) e = p;//记下数据结束位置 } else if( *p=='>' ) { std::string tag( pos + 1, p - pos - 1 ); reArrange(tag); if( is_version( tag ) ) ;//std::cout << tag << "\n"; else if(is_help(tag)) ; else if( is_end( tag ) ) { if( s && e ) { std::string data( s + 1, e -s - 1 ); on_data( data ); s = e = 0; } on_end( tag ); } else if( is_element( tag ) ) { parse_property( tag ); on_end( tag ); } else { parse_property( tag ); s = p;//记下数据开位置 } } p++; len--; } }
void websocket_hybi_17::handle_data(bool is_binary) { if ( state() != OPEN ) { return; } std::istreambuf_iterator<char> beg(&read_buf_), end; buffer data(beg, end); if ( !is_client_side() ) { bool const is_masked = (frame_start_[1] & 0x80) != 0; _aspect_assert(is_masked); for (size_t i = 0, count = data.size(); i != count; ++i) { data[i] ^= frame_mask_[i % 4]; } } on_data(data, is_binary); }
void EmitterBase::close(Callback<> cb) { if (close_pending) { /* * Rationale for throwing rather than ignoring: (1) it was the * behavior before we started refactoring; (2) the user expects * a callback to be called after close is successful. If we do * ignore subsequent close attempts, the promise that the callback * will be called is silently broken, and it seems instead better * to inform the caller that there is a problem with the code * because `close()` has been called more than once. */ throw std::runtime_error("close already pending"); } close_pending = true; shutdown(); on_connect(nullptr); on_data(nullptr); on_flush(nullptr); on_error(nullptr); close_cb = cb; }
void Parser::checkOutputBuffer() { int to_read = 0; int nread = 0; /* is there data we need to send? */ int pending = BIO_ctrl_pending(out_bio); if (pending <= 0) { return; } while(pending) { /* how many bytes to read. */ if (pending >= DTLS_BUFFER_SIZE) { to_read = DTLS_BUFFER_SIZE; } else { to_read = pending; } nread = BIO_read(out_bio, buffer, to_read); if (nread != to_read) { printf("dtls::Parser - error: failed readig the necessary amount of bytes from the out bio.\n"); exit(1); } if (on_data) { on_data(buffer, nread, user); } pending -= to_read; } printf("dtls::Parser - verbose: pending in out_bio: %d\n", pending); }
void HttpServerConnection::read() { while(!is_closed()) { switch(read_state) { case LINE: // get the request line try { if(!async_read_in(line,sizeof(uri)-1)) return; } catch(EndOfStreamError*) { if(!count) throw; // so we get end-of-stream when keep-alive? no problem return; } if(!line.ends_with("\r\n",2)) HttpError::Throw(HttpError::ERequestURITooLong,*this); if(!memcmp(line.cstr(),"\r\n",3)) { // empty lines are ok before request line line.clear(); continue; } count++; read_state = HEADER; { const char* method = strtok(line.cstr()," "); strncpy(uri,strtok(NULL," \r"),sizeof(this->uri)); const char* v = strtok(NULL,"\r"); if(!memcmp(v,"HTTP/1.1",9)) version = HTTP_1_1; else if(!memcmp(v,"HTTP/1.0",9)) version = HTTP_1_0; else version = HTTP_0_9; in_encoding_chunked = false; in_content_length = -1; // not known keep_alive = out_encoding_chunked = (HTTP_1_1 == version); on_request(method,uri); } line.clear(); break; case HEADER: if(!async_read_in(line)) return; if(!memcmp("\r\n",line.cstr(),3)) { read_state = BODY; if(keep_alive && !in_encoding_chunked && (-1 == in_content_length)) in_content_length = 0; // length isn't specified, yet its keep-alive, so there is no content line.clear(); on_body(); break; } if(!line.ends_with("\r\n",2)) HttpError::Throw(HttpError::ERequestEntityTooLarge,*this); { const char* header = strtok(line.cstr()," "), *value = strtok(NULL,"\r"); if(!ends_with(header,":",1)) HttpError::Throw(HttpError::EBadRequest,*this); if((write_state == LINE) && !strcasecmp(header,"connection:") && !strcasecmp(value,"keep-alive")) keep_alive = true; else if(!strcasecmp(header,"content-length:")) { in_content_length = atoi(value); if(in_content_length < 0) HttpError::Throw(HttpError::EBadRequest,*this); } else if(!strcasecmp(header,"transfer-encoding:")) in_encoding_chunked = !strcasecmp(value,"chunked"); on_header(header,value); } line.clear(); break; case BODY: if(in_encoding_chunked) { //RFC2616-s4.4 says this overrides any explicit content-length header ThrowInternalError("in encoding chunked not implemented yet"); } else if(!keep_alive && (-1 == in_content_length)) { // read all available uint8_t* chunk; while(uint16_t len = async_read_buffered(chunk)) on_data(chunk,len); } else if(-1 != in_content_length) { // read all available while(in_content_length) { uint8_t* chunk; if(const uint16_t len = async_read_buffered(chunk,in_content_length)) { in_content_length -= len; on_data(chunk,len); } else return; } if(!keep_alive) { read_state = FINISHED; shutdown(fd,SHUT_RD); return; } read_state = LINE; } else ThrowInternalError("cannot cope with combination of keep_alive %d, content_length %d and encoding_chunked %d", keep_alive,in_content_length,in_encoding_chunked); break; default: ThrowInternalError("unexpected read_state"); } } }
int main ( int argc, char* argv[] ) { int e; pgm_error_t* pgm_err = NULL; setlocale (LC_ALL, ""); log_init (); g_message ("syncrecv"); if (!pgm_init (&pgm_err)) { g_error ("Unable to start PGM engine: %s", pgm_err->message); pgm_error_free (pgm_err); return EXIT_FAILURE; } /* parse program arguments */ const char* binary_name = strrchr (argv[0], '/'); int c; while ((c = getopt (argc, argv, "s:n:p:lh")) != -1) { switch (c) { case 'n': g_network = optarg; break; case 's': g_port = atoi (optarg); break; case 'p': g_udp_encap_port = atoi (optarg); break; case 'l': g_multicast_loop = TRUE; break; case 'h': case '?': usage (binary_name); } } g_quit = FALSE; #ifdef G_OS_UNIX e = pipe (g_quit_pipe); #else e = _pipe (g_quit_pipe, 4096, _O_BINARY | _O_NOINHERIT); #endif g_assert (0 == e); /* setup signal handlers */ signal(SIGSEGV, on_sigsegv); signal(SIGINT, on_signal); signal(SIGTERM, on_signal); #ifdef SIGHUP signal(SIGHUP, SIG_IGN); #endif if (!on_startup()) { g_error ("startup failed"); exit(1); } /* dispatch loop */ g_message ("entering PGM message loop ... "); do { struct timeval tv; int timeout; int n_fds = 2; struct pollfd fds[ 1 + n_fds ]; char buffer[4096]; gsize len; pgm_tsi_t from; const int status = pgm_recvfrom (g_transport, buffer, sizeof(buffer), 0, &len, &from, &pgm_err); switch (status) { case PGM_IO_STATUS_NORMAL: on_data (buffer, len, &from); break; case PGM_IO_STATUS_TIMER_PENDING: pgm_transport_get_timer_pending (g_transport, &tv); goto block; case PGM_IO_STATUS_RATE_LIMITED: pgm_transport_get_rate_remaining (g_transport, &tv); case PGM_IO_STATUS_WOULD_BLOCK: /* poll for next event */ block: timeout = PGM_IO_STATUS_WOULD_BLOCK == status ? -1 : ((tv.tv_sec * 1000) + (tv.tv_usec / 1000)); memset (fds, 0, sizeof(fds)); fds[0].fd = g_quit_pipe[0]; fds[0].events = POLLIN; pgm_transport_poll_info (g_transport, &fds[1], &n_fds, POLLIN); poll (fds, 1 + n_fds, timeout /* ms */); break; default: if (pgm_err) { g_warning ("%s", pgm_err->message); pgm_error_free (pgm_err); pgm_err = NULL; } if (PGM_IO_STATUS_ERROR == status) break; } } while (!g_quit); g_message ("message loop terminated, cleaning up."); /* cleanup */ close (g_quit_pipe[0]); close (g_quit_pipe[1]); if (g_transport) { g_message ("destroying transport."); pgm_transport_destroy (g_transport, TRUE); g_transport = NULL; } g_message ("PGM engine shutdown."); pgm_shutdown (); g_message ("finished."); return EXIT_SUCCESS; }
int main ( int argc, char* argv[] ) { pgm_error_t* pgm_err = NULL; setlocale (LC_ALL, ""); #ifndef _WIN32 puts ("プリン プリン"); #else _putws (L"プリン プリン"); #endif if (!pgm_init (&pgm_err)) { fprintf (stderr, "Unable to start PGM engine: %s\n", pgm_err->message); pgm_error_free (pgm_err); return EXIT_FAILURE; } /* parse program arguments */ const char* binary_name = strrchr (argv[0], '/'); int c; while ((c = getopt (argc, argv, "s:n:p:f:K:N:lih")) != -1) { switch (c) { case 'n': network = optarg; break; case 's': port = atoi (optarg); break; case 'p': udp_encap_port = atoi (optarg); break; case 'f': use_fec = TRUE; break; case 'K': rs_k = atoi (optarg); break; case 'N': rs_n = atoi (optarg); break; case 'l': use_multicast_loop = TRUE; break; case 'i': pgm_if_print_all(); return EXIT_SUCCESS; case 'h': case '?': usage (binary_name); } } if (use_fec && ( !rs_n || !rs_k )) { fprintf (stderr, "Invalid Reed-Solomon parameters RS(%d,%d).\n", rs_n, rs_k); usage (binary_name); } /* setup signal handlers */ #ifdef SIGHUP signal (SIGHUP, SIG_IGN); #endif #ifndef _WIN32 int e = pipe (terminate_pipe); assert (0 == e); signal (SIGINT, on_signal); signal (SIGTERM, on_signal); #else terminate_event = CreateEvent (NULL, TRUE, FALSE, TEXT("TerminateEvent")); SetConsoleCtrlHandler ((PHANDLER_ROUTINE)on_console_ctrl, TRUE); #endif /* !_WIN32 */ if (!on_startup()) { fprintf (stderr, "Startup failed\n"); return EXIT_FAILURE; } /* dispatch loop */ #ifndef _WIN32 int fds; fd_set readfds; #else int n_handles = 3, recv_sock, pending_sock; HANDLE waitHandles[ 3 ]; DWORD dwTimeout, dwEvents; WSAEVENT recvEvent, pendingEvent; recvEvent = WSACreateEvent (); pgm_getsockopt (sock, PGM_RECV_SOCK, &recv_sock, sizeof(recv_sock)); WSAEventSelect (recv_sock, recvEvent, FD_READ); pendingEvent = WSACreateEvent (); pgm_getsockopt (sock, PGM_PENDING_SOCK, &pending_sock, sizeof(pending_sock)); WSAEventSelect (pending_sock, pendingEvent, FD_READ); waitHandles[0] = terminate_event; waitHandles[1] = recvEvent; waitHandles[2] = pendingEvent; #endif /* !_WIN32 */ puts ("Entering PGM message loop ... "); do { struct timeval tv; char buffer[4096]; size_t len; pgm_tsi_t from; const int status = pgm_recvfrom (sock, buffer, sizeof(buffer), 0, &len, &from, &pgm_err); switch (status) { case PGM_IO_STATUS_NORMAL: on_data (buffer, len, &from); break; case PGM_IO_STATUS_TIMER_PENDING: pgm_getsockopt (sock, PGM_TIME_REMAIN, &tv, sizeof(tv)); goto block; case PGM_IO_STATUS_RATE_LIMITED: pgm_getsockopt (sock, PGM_RATE_REMAIN, &tv, sizeof(tv)); case PGM_IO_STATUS_WOULD_BLOCK: /* select for next event */ block: #ifndef _WIN32 fds = terminate_pipe[0] + 1; FD_ZERO(&readfds); FD_SET(terminate_pipe[0], &readfds); pgm_select_info (sock, &readfds, NULL, &fds); fds = select (fds, &readfds, NULL, NULL, PGM_IO_STATUS_WOULD_BLOCK == status ? NULL : &tv); #else dwTimeout = PGM_IO_STATUS_WOULD_BLOCK == status ? INFINITE : (DWORD)((tv.tv_sec * 1000) + (tv.tv_usec / 1000)); dwEvents = WaitForMultipleObjects (n_handles, waitHandles, FALSE, dwTimeout); switch (dwEvents) { case WAIT_OBJECT_0+1: WSAResetEvent (recvEvent); break; case WAIT_OBJECT_0+2: WSAResetEvent (pendingEvent); break; default: break; } #endif /* !_WIN32 */ break; default: if (pgm_err) { fprintf (stderr, "%s\n", pgm_err->message); pgm_error_free (pgm_err); pgm_err = NULL; } if (PGM_IO_STATUS_ERROR == status) break; } } while (!is_terminated); puts ("Message loop terminated, cleaning up."); /* cleanup */ #ifndef _WIN32 close (terminate_pipe[0]); close (terminate_pipe[1]); #else WSACloseEvent (recvEvent); WSACloseEvent (pendingEvent); CloseHandle (terminate_event); #endif /* !_WIN32 */ if (sock) { puts ("Destroying PGM socket."); pgm_close (sock, TRUE); sock = NULL; } puts ("PGM engine shutdown."); pgm_shutdown (); puts ("finished."); return EXIT_SUCCESS; }
int main ( int argc, char* argv[] ) { pgm_error_t* pgm_err = NULL; setlocale (LC_ALL, ""); #ifndef _WIN32 puts ("いちごのショートケーキ"); #else puts ("ichigo no shōtokēki"); #endif if (!pgm_init (&pgm_err)) { fprintf (stderr, "Unable to start PGM engine: %s\n", pgm_err->message); pgm_error_free (pgm_err); return EXIT_FAILURE; } /* parse program arguments */ #ifdef _WIN32 const char* binary_name = strrchr (argv[0], '\\'); #else const char* binary_name = strrchr (argv[0], '/'); #endif if (NULL == binary_name) binary_name = argv[0]; else binary_name++; int c; while ((c = getopt (argc, argv, "s:n:p:f:K:N:lih")) != -1) { switch (c) { case 'n': network = optarg; break; case 's': port = atoi (optarg); break; case 'p': udp_encap_port = atoi (optarg); break; case 'f': use_fec = TRUE; break; case 'K': rs_k = atoi (optarg); break; case 'N': rs_n = atoi (optarg); break; case 'l': use_multicast_loop = TRUE; break; case 'i': pgm_if_print_all(); return EXIT_SUCCESS; case 'h': case '?': usage (binary_name); } } if (use_fec && ( !rs_n || !rs_k )) { fprintf (stderr, "Invalid Reed-Solomon parameters RS(%d,%d).\n", rs_n, rs_k); usage (binary_name); } /* setup signal handlers */ #ifdef SIGHUP signal (SIGHUP, SIG_IGN); #endif #ifndef _WIN32 int e = pipe (terminate_pipe); assert (0 == e); signal (SIGINT, on_signal); signal (SIGTERM, on_signal); #else terminateEvent = WSACreateEvent (); SetConsoleCtrlHandler ((PHANDLER_ROUTINE)on_console_ctrl, TRUE); setvbuf (stdout, (char *) NULL, _IONBF, 0); #endif /* !_WIN32 */ if (!on_startup()) { fprintf (stderr, "Startup failed\n"); return EXIT_FAILURE; } /* dispatch loop */ #ifndef _WIN32 int fds, read_fd = async_get_socket (async); fd_set readfds; #else DWORD cEvents = 2; WSAEVENT waitEvents[ 2 ]; DWORD dwEvents; waitEvents[0] = terminateEvent; waitEvents[1] = async_get_event (async); #endif /* !_WIN32 */ puts ("Entering PGM message loop ... "); do { char buffer[4096]; struct pgm_sockaddr_t from; socklen_t fromlen = sizeof (from); const ssize_t len = async_recvfrom (async, buffer, sizeof(buffer), &from, &fromlen); if (len >= 0) { on_data (buffer, len, &from); } else { #ifndef _WIN32 fds = MAX(terminate_pipe[0], read_fd) + 1; FD_ZERO(&readfds); FD_SET(terminate_pipe[0], &readfds); FD_SET(read_fd, &readfds); fds = select (fds, &readfds, NULL, NULL, NULL); #else dwEvents = WSAWaitForMultipleEvents (cEvents, waitEvents, FALSE, WSA_INFINITE, FALSE); switch (dwEvents) { case WSA_WAIT_EVENT_0+1: WSAResetEvent (waitEvents[1]); break; default: break; } #endif /* _WIN32 */ } } while (!is_terminated); puts ("Message loop terminated, cleaning up."); /* cleanup */ #ifndef _WIN32 close (terminate_pipe[0]); close (terminate_pipe[1]); #else WSACloseEvent (terminateEvent); #endif /* !_WIN32 */ if (async) { puts ("Destroying asynchronous queue."); async_destroy (async); async = NULL; } if (sock) { puts ("Closing PGM socket."); pgm_close (sock, TRUE); sock = NULL; } puts ("PGM engine shutdown."); pgm_shutdown (); puts ("finished."); return EXIT_SUCCESS; }
int main ( int argc, char* argv[] ) { pgm_error_t* pgm_err = NULL; setlocale (LC_ALL, ""); log_init (); g_message ("blocksyncrecv"); if (!pgm_init (&pgm_err)) { g_error ("Unable to start PGM engine: %s", pgm_err->message); pgm_error_free (pgm_err); return EXIT_FAILURE; } /* parse program arguments */ const char* binary_name = strrchr (argv[0], '/'); int c; while ((c = getopt (argc, argv, "s:n:p:lh")) != -1) { switch (c) { case 'n': g_network = optarg; break; case 's': g_port = atoi (optarg); break; case 'p': g_udp_encap_port = atoi (optarg); break; case 'l': g_multicast_loop = TRUE; break; case 'h': case '?': usage (binary_name); } } /* setup signal handlers */ signal(SIGSEGV, on_sigsegv); #ifdef SIGHUP signal(SIGHUP, SIG_IGN); #endif #ifdef G_OS_UNIX signal(SIGINT, on_signal); signal(SIGTERM, on_signal); #else SetConsoleCtrlHandler ((PHANDLER_ROUTINE)on_console_ctrl, TRUE); setvbuf (stdout, (char *) NULL, _IONBF, 0); #endif on_startup(); /* dispatch loop */ g_message ("entering PGM message loop ... "); do { char buffer[4096]; size_t len; struct pgm_sockaddr_t from; socklen_t fromlen = sizeof(from); const int status = pgm_recvfrom (g_sock, buffer, sizeof(buffer), 0, &len, &from, &fromlen, &pgm_err); if (PGM_IO_STATUS_NORMAL == status) on_data (buffer, len, &from); else { if (pgm_err) { g_warning ("%s", pgm_err->message); pgm_error_free (pgm_err); pgm_err = NULL; } if (PGM_IO_STATUS_ERROR == status) break; } } while (!g_quit); g_message ("message loop terminated, cleaning up."); /* cleanup */ if (g_sock) { g_message ("closing PGM socket."); pgm_close (g_sock, TRUE); g_sock = NULL; } g_message ("PGM engine shutdown."); pgm_shutdown (); g_message ("finished."); return EXIT_SUCCESS; }
int main ( int argc, char* argv[] ) { pgm_error_t* pgm_err = NULL; setlocale (LC_ALL, ""); #if !defined(_WIN32) puts ("プリン プリン"); #else /* Windows consoles have incredibly limited Unicode support */ puts ("purin purin"); #endif if (!pgm_init (&pgm_err)) { fprintf (stderr, "Unable to start PGM engine: %s\n", pgm_err->message); pgm_error_free (pgm_err); return EXIT_FAILURE; } /* parse program arguments */ #ifdef _WIN32 const char* binary_name = strrchr (argv[0], '\\'); #else const char* binary_name = strrchr (argv[0], '/'); #endif if (NULL == binary_name) binary_name = argv[0]; else binary_name++; int c; while ((c = getopt (argc, argv, "s:n:p:cf:K:N:lih")) != -1) { switch (c) { case 'n': network = optarg; break; case 's': port = atoi (optarg); break; case 'p': udp_encap_port = atoi (optarg); break; case 'c': use_pgmcc = TRUE; break; case 'f': use_fec = TRUE; break; case 'K': rs_k = atoi (optarg); break; case 'N': rs_n = atoi (optarg); break; case 'l': use_multicast_loop = TRUE; break; case 'i': pgm_if_print_all(); return EXIT_SUCCESS; case 'h': case '?': usage (binary_name); } } if (use_fec && ( !rs_n || !rs_k )) { fprintf (stderr, "Invalid Reed-Solomon parameters RS(%d,%d).\n", rs_n, rs_k); usage (binary_name); } /* setup signal handlers */ #ifdef SIGHUP signal (SIGHUP, SIG_IGN); #endif #ifndef _WIN32 int e = pipe (terminate_pipe); assert (0 == e); signal (SIGINT, on_signal); signal (SIGTERM, on_signal); #else terminateEvent = WSACreateEvent(); SetConsoleCtrlHandler ((PHANDLER_ROUTINE)on_console_ctrl, TRUE); setvbuf (stdout, (char *) NULL, _IONBF, 0); #endif /* !_WIN32 */ if (!on_startup()) { fprintf (stderr, "Startup failed\n"); return EXIT_FAILURE; } /* dispatch loop */ #ifndef _WIN32 int fds; fd_set readfds; #else SOCKET recv_sock, pending_sock; DWORD cEvents = PGM_RECV_SOCKET_READ_COUNT + 1; WSAEVENT waitEvents[ PGM_RECV_SOCKET_READ_COUNT + 1 ]; socklen_t socklen = sizeof (SOCKET); waitEvents[0] = terminateEvent; waitEvents[1] = WSACreateEvent(); waitEvents[2] = WSACreateEvent(); assert (2 == PGM_RECV_SOCKET_READ_COUNT); pgm_getsockopt (sock, IPPROTO_PGM, PGM_RECV_SOCK, &recv_sock, &socklen); WSAEventSelect (recv_sock, waitEvents[1], FD_READ); pgm_getsockopt (sock, IPPROTO_PGM, PGM_PENDING_SOCK, &pending_sock, &socklen); WSAEventSelect (pending_sock, waitEvents[2], FD_READ); #endif /* !_WIN32 */ puts ("Entering PGM message loop ... "); do { struct timeval tv; #ifdef _WIN32 DWORD dwTimeout, dwEvents; #endif char buffer[4096]; size_t len; struct pgm_sockaddr_t from; socklen_t fromlen = sizeof (from); const int status = pgm_recvfrom (sock, buffer, sizeof(buffer), 0, &len, &from, &fromlen, &pgm_err); switch (status) { case PGM_IO_STATUS_NORMAL: on_data (buffer, len, &from); break; case PGM_IO_STATUS_TIMER_PENDING: { socklen_t optlen = sizeof (tv); pgm_getsockopt (sock, IPPROTO_PGM, PGM_TIME_REMAIN, &tv, &optlen); } goto block; case PGM_IO_STATUS_RATE_LIMITED: { socklen_t optlen = sizeof (tv); pgm_getsockopt (sock, IPPROTO_PGM, PGM_RATE_REMAIN, &tv, &optlen); } case PGM_IO_STATUS_WOULD_BLOCK: /* select for next event */ block: #ifndef _WIN32 fds = terminate_pipe[0] + 1; FD_ZERO(&readfds); FD_SET(terminate_pipe[0], &readfds); pgm_select_info (sock, &readfds, NULL, &fds); fds = select (fds, &readfds, NULL, NULL, PGM_IO_STATUS_WOULD_BLOCK == status ? NULL : &tv); #else dwTimeout = PGM_IO_STATUS_WOULD_BLOCK == status ? WSA_INFINITE : (DWORD)((tv.tv_sec * 1000) + (tv.tv_usec / 1000)); dwEvents = WSAWaitForMultipleEvents (cEvents, waitEvents, FALSE, dwTimeout, FALSE); switch (dwEvents) { case WSA_WAIT_EVENT_0+1: WSAResetEvent (waitEvents[1]); break; case WSA_WAIT_EVENT_0+2: WSAResetEvent (waitEvents[2]); break; default: break; } #endif /* !_WIN32 */ break; default: if (pgm_err) { fprintf (stderr, "%s\n", pgm_err->message); pgm_error_free (pgm_err); pgm_err = NULL; } if (PGM_IO_STATUS_ERROR == status) break; } } while (!is_terminated); puts ("Message loop terminated, cleaning up."); /* cleanup */ #ifndef _WIN32 close (terminate_pipe[0]); close (terminate_pipe[1]); #else WSACloseEvent (waitEvents[0]); WSACloseEvent (waitEvents[1]); WSACloseEvent (waitEvents[2]); #endif /* !_WIN32 */ if (sock) { puts ("Destroying PGM socket."); pgm_close (sock, TRUE); sock = NULL; } puts ("PGM engine shutdown."); pgm_shutdown (); puts ("finished."); return EXIT_SUCCESS; }