#include #include #include #include #include #include #include #include #include static void* wait_a_second_and_resume( void *arg ) { fprintf( stderr, "thread: wait a second\n" ); sleep( 1 ); fprintf( stderr, "thread: resume connection\n" ); struct MHD_Connection *connection = (struct MHD_Connection *)arg; MHD_resume_connection( connection ); return NULL; } static int http_AccessHandlerCallback( void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **con_cls ) { // Do never respond on first call (especially POST wait for "100 Continue") if( *con_cls == NULL ) { fprintf( stderr, "callback: first call\n" ); int *status = (int*) malloc( sizeof(int) ); *status = 0; *con_cls = status; return MHD_YES; } int *status = (int*)*con_cls; // Second call: create a thead and suspend connection if( *status == 0 ) { fprintf( stderr, "callback: second call\n" ); *status = 1; MHD_suspend_connection( connection ); pthread_t thread_id; pthread_attr_t thread_attr; pthread_attr_init( &thread_attr ); pthread_create( &thread_id, &thread_attr, wait_a_second_and_resume, connection ); return MHD_YES; } // Third call: create response { fprintf( stderr, "callback: third call\n" ); static char html[] = "\n" "Response\n" "

Response

\n" "\n"; struct MHD_Response *response = MHD_create_response_from_buffer( strlen(html), html, MHD_RESPMEM_PERSISTENT ); MHD_queue_response( connection, MHD_HTTP_OK, response ); MHD_destroy_response( response ); return MHD_YES; } } int main() { // create a socket on port 8080 int ai_family = AF_INET; struct sockaddr addr_socket; struct sockaddr_in *in_addr = (struct sockaddr_in *) &addr_socket; memset( in_addr, 0, sizeof(*in_addr) ); in_addr->sin_family = AF_INET; in_addr->sin_port = htons( 8080 ); in_addr->sin_addr.s_addr = htonl( INADDR_ANY ); socklen_t addr_len = sizeof(*in_addr); // Create socket int listening_socket = socket( ai_family, SOCK_STREAM, IPPROTO_TCP ); if( listening_socket == -1 ) { fprintf( stderr, "Could not create socket: %s.\n", strerror(errno) ); return EXIT_FAILURE; } // Non blocking socket int file_descriptor_flag = fcntl( listening_socket, F_GETFL ); fcntl( listening_socket, F_SETFL, file_descriptor_flag | O_NONBLOCK ); // Bind socket int bound = bind( listening_socket, &addr_socket, addr_len ); if( bound == -1 ) { close( listening_socket ); fprintf( stderr, "Bind failed: %s\n", strerror(errno) ); return EXIT_FAILURE; } // Start listening int listening = listen( listening_socket, 31 ); if( listening == -1 ) { close( listening_socket ); fprintf( stderr, "Listen failed: %s\n", strerror(errno) ); return EXIT_FAILURE; } // Create daemon unsigned int daemon_flags = MHD_USE_SELECT_INTERNALLY | MHD_USE_EPOLL_LINUX_ONLY | MHD_USE_SUSPEND_RESUME | MHD_USE_PIPE_FOR_SHUTDOWN; struct MHD_OptionItem options[] = { { MHD_OPTION_LISTEN_SOCKET, listening_socket, NULL }, { MHD_OPTION_THREAD_POOL_SIZE, 1, NULL }, { MHD_OPTION_END, 0, NULL } }; struct MHD_Daemon *daemon = MHD_start_daemon( daemon_flags, 0, NULL, NULL, http_AccessHandlerCallback, NULL, MHD_OPTION_ARRAY, options, MHD_OPTION_END ); if( daemon == NULL ) return EXIT_FAILURE; sleep( 10000 ); // Stop daemon MHD_stop_daemon( daemon ); return EXIT_SUCCESS; }