@@ -196,6 +196,9 @@ class Server {
196196 void set_error_handler (Handler handler);
197197 void set_logger (Logger logger);
198198
199+ int bind_to_any_port (const char * host, int socket_flags = 0 );
200+ bool listen_after_bind ();
201+
199202 bool listen (const char * host, int port, int socket_flags = 0 );
200203
201204 bool is_running () const ;
@@ -210,6 +213,8 @@ class Server {
210213 typedef std::vector<std::pair<std::regex, Handler>> Handlers;
211214
212215 socket_t create_server_socket (const char * host, int port, int socket_flags) const ;
216+ int bind_internal (const char * host, int port, int socket_flags);
217+ bool listen_internal ();
213218
214219 bool routing (Request& req, Response& res);
215220 bool handle_file_request (Request& req, Response& res);
@@ -1399,49 +1404,20 @@ inline void Server::set_logger(Logger logger)
13991404 logger_ = logger;
14001405}
14011406
1402- inline bool Server::listen (const char * host, int port , int socket_flags)
1407+ inline int Server::bind_to_any_port (const char * host, int socket_flags)
14031408{
1404- if (!is_valid ()) {
1405- return false ;
1406- }
1407-
1408- svr_sock_ = create_server_socket (host, port, socket_flags);
1409- if (svr_sock_ == -1 ) {
1410- return false ;
1411- }
1412-
1413- auto ret = true ;
1414-
1415- for (;;) {
1416- auto val = detail::select_read (svr_sock_, 0 , 100000 );
1417-
1418- if (val == 0 ) { // Timeout
1419- if (svr_sock_ == -1 ) {
1420- // The server socket was closed by 'stop' method.
1421- break ;
1422- }
1423- continue ;
1424- }
1425-
1426- socket_t sock = accept (svr_sock_, NULL , NULL );
1427-
1428- if (sock == -1 ) {
1429- if (svr_sock_ != -1 ) {
1430- detail::close_socket (svr_sock_);
1431- ret = false ;
1432- } else {
1433- ; // The server socket was closed by user.
1434- }
1435- break ;
1436- }
1409+ return bind_internal (host, 0 , socket_flags);
1410+ }
14371411
1438- // TODO: Use thread pool...
1439- std::thread ([=]() {
1440- read_and_close_socket (sock);
1441- }).detach ();
1442- }
1412+ inline bool Server::listen_after_bind () {
1413+ return listen_internal ();
1414+ }
14431415
1444- return ret;
1416+ inline bool Server::listen (const char * host, int port, int socket_flags)
1417+ {
1418+ if (bind_internal (host, port, socket_flags) < 0 )
1419+ return false ;
1420+ return listen_internal ();
14451421}
14461422
14471423inline bool Server::is_running () const
@@ -1560,6 +1536,65 @@ inline socket_t Server::create_server_socket(const char* host, int port, int soc
15601536 }, socket_flags);
15611537}
15621538
1539+ inline int Server::bind_internal (const char * host, int port, int socket_flags)
1540+ {
1541+ if (!is_valid ()) {
1542+ return -1 ;
1543+ }
1544+
1545+ svr_sock_ = create_server_socket (host, port, socket_flags);
1546+ if (svr_sock_ == -1 ) {
1547+ return -1 ;
1548+ }
1549+
1550+ if (port == 0 ) {
1551+ struct sockaddr_in sin;
1552+ socklen_t len = sizeof (sin);
1553+ if (getsockname (svr_sock_, reinterpret_cast <struct sockaddr *>(&sin), &len) == -1 ) {
1554+ return -1 ;
1555+ }
1556+ return ntohs (sin.sin_port );
1557+ } else {
1558+ return port;
1559+ }
1560+ }
1561+
1562+ inline bool Server::listen_internal ()
1563+ {
1564+ auto ret = true ;
1565+
1566+ for (;;) {
1567+ auto val = detail::select_read (svr_sock_, 0 , 100000 );
1568+
1569+ if (val == 0 ) { // Timeout
1570+ if (svr_sock_ == -1 ) {
1571+ // The server socket was closed by 'stop' method.
1572+ break ;
1573+ }
1574+ continue ;
1575+ }
1576+
1577+ socket_t sock = accept (svr_sock_, NULL , NULL );
1578+
1579+ if (sock == -1 ) {
1580+ if (svr_sock_ != -1 ) {
1581+ detail::close_socket (svr_sock_);
1582+ ret = false ;
1583+ } else {
1584+ ; // The server socket was closed by user.
1585+ }
1586+ break ;
1587+ }
1588+
1589+ // TODO: Use thread pool...
1590+ std::thread ([=]() {
1591+ read_and_close_socket (sock);
1592+ }).detach ();
1593+ }
1594+
1595+ return ret;
1596+ }
1597+
15631598inline bool Server::routing (Request& req, Response& res)
15641599{
15651600 if (req.method == " GET" && handle_file_request (req, res)) {
0 commit comments