cerr << __FILE__ << "(" << __LINE__ << ")"
<< ": port = " << port << endl;
#endif // DEBUG
- // FIXME
- //cerr << "recvtimeout = " << socket.recvtimeout(1) << endl;
- //cerr << "sendtimeout = " << socket.sendtimeout(1) << endl;
- //cerr << "recvtimeout = " << socket.recvtimeout(1) << endl;
- //cerr << "sendtimeout = " << socket.sendtimeout(1) << endl;
+ socket.reuseaddr(true);
socket.bind(port);
#ifdef DEBUG
cerr << __FILE__ << "(" << __LINE__ << ")"
#endif // DEBUG
}
-/*void TCPServer::finish(bool attach) {
+void TCPServer::finish(void) {
#ifdef DEBUG
cerr << __FILE__ << "(" << __LINE__ << ")"
- << ": finish(attach = " << attach << ");" << endl;
+ << ": finish(void);" << endl;
#endif // DEBUG
- //socket_mutex.lock();
- close(socket.sd());
- //socket.shutdown(sockbuf::shut_readwrite);
- //socket_mutex.unlock();
- Runnable::finish(attach);
-}*/
+ Runnable::finish();
+ // Creo una conexión suicida para que el accept() del server retorne
+ // el control y el server pueda terminar realmente.
+ try {
+ sockinetbuf suicida(sockbuf::sock_stream);
+ suicida.connect(socket.localhost(), socket.localport());
+ } catch (const sockerr& e) {
+ // FIXME mejorar codigos de error.
+ signal_error().emit(100000 + e.serrno(), string("No se pudo crear "
+ "conexión 'suicida' para terminar el servidor: ")
+ + e.errstr());
+ }
+}
void TCPServer::on_connection_finished(Connection* connection) {
#ifdef DEBUG
#endif // DEBUG
}
-/// \todo TODO: ver tema de timeout o como salir de un accept().
-void TCPServer::real_run(void) {
+void TCPServer::real_run(void) throw() {
#ifdef DEBUG
cerr << __FILE__ << "(" << __LINE__ << ")"
<< ": real_run()" << endl;
try {
connection = new_connection(socket.accept());
} catch (const sockerr& e) { // No se si el accept() puede fallar.
- signal_error().emit(e.serrno(), e.errstr());
+ signal_error().emit(e.serrno(),
+ string("Error creando conexión nueva: ") + e.errstr());
continue; // Supongo que puede seguir aceptando conexiones.
}
+ if (!stop()) {
+ // Solo avisamos si la conexión que viene no es para matarnos.
+ _connection_opened(connection->get_host(), connection->get_port());
+ }
#ifdef DEBUG
cerr << __FILE__ << "(" << __LINE__ << ")"
<< ": real_run(): connection = " << connection
<< endl;
#endif // DEBUG
Glib::Mutex::Lock lock(connections_mutex);
- // XXX connections_mutex.lock();
connections.push_back(connection);
#ifdef DEBUG
cerr << __FILE__ << "(" << __LINE__ << ")"
cerr << "\t " << *i << endl;
}
#endif // DEBUG
- // XXX connections_mutex.unlock(); // Si pongo el mutex antes del run(),
- // muere.
// Conecto la señal para cuando termina una conexión, borrarla.
- connection->signal_finished().connect(
- SigC::bind<Connection*>(
- SigC::slot_class(*this,
- &TCPServer::on_connection_finished),
- connection));
+ connection->signal_finished().connect(SigC::bind(
+ SigC::slot_class(*this, &TCPServer::on_connection_finished),
+ connection));
connection->run();
}
}
return cl;
}
+TCPServer::SignalConnectionOpened& TCPServer::signal_connection_opened(void) {
+ return _connection_opened;
+}
+
} // namespace Server
} // namespace PlaQui