string.
- Se arreglan algunos bugs de llamadas a constructores con parametros viejos.
- Se agrega un test minimamente funcional del ControlClient (tiene un bug
soportable).
- Se arreglan algunas otras cosas para que el ControlClient ande (aunque sea
mal :-/).
- Se agrega una TODO list :)
--- /dev/null
+$Id$
+- Agregar timeouts (recvtimeout y sendtimeout).
+- Darle bola al header Connection para saber si cerramos la conexión al
+ finalizar el request o no.
+- Ver por que el ControlClient tira una señal de error despues de una respuesta
+ buena.
/**
* Constructor.
*/
- Command(const std::string& target = "",
- const std::string& command = "");
+ Command(const std::string& _target = "",
+ const std::string& _command = "");
/**
* Establece el destino.
HTTPRequest(const std::string& uri = "/",
const HTTPMethod& method = GET,
const std::string& query = "",
+ const std::string& body = "",
const std::string& version = "1.1");
+ /**
+ * Obtiene el método como un string.
+ */
+ std::string method_str(void) const;
+
/**
* Obtiene los datos del pedido HTTP desde un texto.
*/
/**
* Constructor.
*/
- HTTPResponse(const std::string& version = "1.1");
+ HTTPResponse(const std::string& body = "",
+ const std::string& version = "1.1");
/**
* Constructor.
#endif // DEBUG
}
-Command::Command(const string& target, const string& command):
- target(target), command(command) {
+Command::Command(const string& _target, const string& _command) {
#ifdef DEBUG
cerr << __FILE__ << ": target = " << target << " | "
<< "command = " << command << endl;
#endif // DEBUG
+ set_target(_target);
+ set_command(_command);
}
void Command::build(void) {
ControlClient::ControlClient(string host, int port):
Connection(sockbuf::sock_stream) {
#ifdef DEBUG
- cerr << __FILE__ << ": host" << host
+ cerr << __FILE__ << ": host = " << host
<< " | port = " << port << endl;
#endif // DEBUG
socket->connect(host.c_str(), port);
- if (!socket->is_open()) {
- throw ios::failure("Can't connect!");
- }
+ //if (!socket->is_open()) {
+ // throw ios::failure("Can't connect!");
+ //}
}
void ControlClient::real_run(void) {
#endif // DEBUG
for (HTTPHeaders::const_iterator i = h.begin();
i != h.end(); ++i) {
- os << i->first << ": " << i->second << "\n\r";
+ os << i->first << ": " << i->second << "\r\n";
}
return os;
}
HTTPMessage::HTTPMessage(const string& _body, const string& _version):
version(_version) {
#ifdef DEBUG
- cerr << __FILE__ << ": version = " << version << " | body.length = "
- << _body.length() << endl;
+ cerr << __FILE__ << ": version = " << version << " | body ("
+ << _body.length() << ") = " << _body << endl;
#endif // DEBUG
set_body(_body);
}
body = _body;
if (body.length()) {
stringstream ss; // TODO ver forma mas linda de convertir
- ss << (body.length()+1); // FIXME No se por que tengo que sumarle 1.
+ ss << (body.length()); // FIXME No se por que tengo que sumarle 1.
headers["Accept-Ranges"] = "bytes";
headers["Content-Length"] = ss.str();
}
#ifdef DEBUG
cerr << __FILE__ << ": operator<<()" << endl;
#endif // DEBUG
- return os << m.headers << "\n\r" // Fin de cabeceras
+ return os << m.headers << "\r\n" // Fin de cabeceras
<< m.body;
}
}
HTTPRequest::HTTPRequest(const string& uri, const HTTPMethod& method,
- const string& query, const string& version):
- HTTPMessage(version), method(method), uri(uri), query(query) {
+ const string& query, const string& body, const string& version):
+ HTTPMessage(body, version), method(method), uri(uri), query(query) {
#ifdef DEBUG
cerr << __FILE__ << ": uri = " << uri << " | "
- << "method = " << ((method == GET) ? "GET" : "POST") << " | "
+ << "method = " << method_str() << " | "
<< "query = " << query << " | "
+ << "body.length = " << body.length() << " | "
<< "version = " << version << endl;
#endif // DEBUG
}
+string HTTPRequest::method_str(void) const {
+ switch (method) {
+ case POST:
+ return "POST";
+ case GET:
+ default:
+ return "GET";
+ }
+}
+
istream& operator>>(istream& is, HTTPRequest& req)
throw(HTTPError, ios::failure) {
#ifdef DEBUG
#ifdef DEBUG
cerr << __FILE__ << ": operator<<()" << endl;
#endif // DEBUG
- os << req.method << " " << req.uri;
+ os << req.method_str() << " " << req.uri;
if (req.query.length()) {
os << "?" << req.query;
}
- // TODO ver que este bien el \n/r
- os << " HTTP/" << req.version << "\n\r" << static_cast<const HTTPMessage&>(req);
+ os << " HTTP/" << req.version << "\r\n"
+ << static_cast<const HTTPMessage&>(req);
return os;
}
#endif // DEBUG
}
-HTTPResponse::HTTPResponse(const string& version):
- HTTPMessage(version) {
+HTTPResponse::HTTPResponse(const string& body, const string& version):
+ HTTPMessage(body, version) {
#ifdef DEBUG
- cerr << __FILE__ << ": version = " << version << endl;
+ cerr << __FILE__ << ": body.length = " << body.length()
+ << " | version = " << version << endl;
#endif // DEBUG
}
}
// Averiguo la versión.
string::size_type pos = line.find_first_of(String::SPACE_CHARS, 5);
- string ver = line.substr(5, pos);
+ string ver = line.substr(5, pos - 5);
if ((ver == "1.1") || (ver == "1.0")) {
resp.version = ver;
} else {
cerr << __FILE__ << ": operator<<()" << endl;
#endif // DEBUG
os << "HTTP/" << resp.version << " " << resp.status_code << " "
- << HTTPMessage::reason(resp.status_code) << "\n\r";
- // TODO ver que este bien el \r\l
+ << HTTPMessage::reason(resp.status_code) << "\r\n";
os << static_cast<const HTTPMessage&>(resp);
return os;
}
response.set_body("Invalid command for 'connection' taget!");
}
} else if (command.get_target() == "transmission") {
+ response.status_code = HTTPMessage::NOT_FOUND;
+ response.set_body("Invalid command for 'transmission' taget!");
} else if (command.get_target() == "plant") {
+ response.status_code = HTTPMessage::NOT_FOUND;
+ response.set_body("Invalid command for 'plant' taget!");
} else {
response.status_code = HTTPMessage::NOT_FOUND;
response.set_body("Invalid Target!");
response.headers["Content-Type"] = "text/html; charset=iso-8859-1";
response.headers["Connection"] = "close";
server->send(response);
- server->finish();
+ // FIXME con timeout no debería ser necesario. Verificar cabecera Connection
+ // para saber si hay que finish()earlo o no.
+ // server->finish();
}
} // namespace Server
#CXXFLAGS+=-O3
LDFLAGS=-lsocket++ `pkg-config --libs glibmm-2.0 gthread-2.0` #-L$(LIB_FILES)
-TARGETS=server_test
+TARGETS=server_test client_test
# Regla por defecto.
all: $(TARGETS)
# Tests
server_test: $(LIB_FILES)/server.a server_test.o
+# Tests
+client_test: $(LIB_FILES)/server.a client_test.o
+
clean:
rm -f $(TARGETS) *.o