Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStijn Buys <ingar@osirion.org>2008-03-21 19:25:11 +0000
committerStijn Buys <ingar@osirion.org>2008-03-21 19:25:11 +0000
commit2314c27dd650dc02c0b5bdd3bef75818393a9ab5 (patch)
tree231815c866a1330338d976480284250e99207554 /src/core/netconnection.cc
parent7e99fac4552b402034e5fc3e833cbe8c274f95ce (diff)
switched to UDP networking
Diffstat (limited to 'src/core/netconnection.cc')
-rw-r--r--src/core/netconnection.cc167
1 files changed, 135 insertions, 32 deletions
diff --git a/src/core/netconnection.cc b/src/core/netconnection.cc
index 9790655..379df14 100644
--- a/src/core/netconnection.cc
+++ b/src/core/netconnection.cc
@@ -7,7 +7,6 @@
#include <sstream>
#include "sys/sys.h"
-#include "net/net.h"
#include "core/application.h"
#include "core/gameconnection.h"
#include "core/netconnection.h"
@@ -22,27 +21,86 @@ NetConnection::NetConnection()
NetConnection::~NetConnection()
{
+ disconnect();
+}
+
+void NetConnection::abort()
+{
+ connection_error= true;
}
void NetConnection::connect(std::string const &to_host, int to_port)
{
- TCPConnection::connect(to_host, to_port);
- if(connected()) {
- FD_ZERO(&clientset);
- FD_SET(fd(), &clientset);
+ connection_error = false;
+ connection_fd = -1;
+
+ if (valid())
+ return;
+
+ // resolve serverhostname
+ struct hostent *serverhostent;
+ serverhostent = gethostbyname(to_host.c_str());
+ if (!serverhostent) {
+ con_warn << "Could not resolve '" << to_host.c_str() << "'" << std::endl;
+ abort();
+ return;
}
+
+ con_print << "Connecting to " << inet_ntoa(*((struct in_addr *)serverhostent->h_addr)) << ":" << to_port << "..." << std::endl;
+
+ // Get a socket file descriptor
+ connection_fd = socket(PF_INET, SOCK_DGRAM, 0);
+ if (connection_fd == -1) {
+ //con_error << "Network socket() failed!" << std::endl;
+ abort();
+ return;
+ }
+
+ // make the connection
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = htons(to_port);
+ // FIXME inet_addr can still fail
+ server_addr.sin_addr.s_addr = inet_addr(inet_ntoa(*((struct in_addr *)serverhostent->h_addr)));
+ if (server_addr.sin_addr.s_addr == INADDR_NONE) {
+ con_error << "Network invalid address " << to_host << "!" << std::endl;
+ abort();
+ return;
+ }
+ memset(server_addr.sin_zero, '\0', sizeof server_addr.sin_zero);
+
+ /*
+ if (::connect(connection_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) != 0) {
+ //con_error << "Network connect() failed!" << std::endl;
+ abort();
+ return;
+ }
+ */
+
+ connection_host = to_host;
+ connection_port = to_port;
+ connection_error = false;
- std::ostringstream osstream;
- osstream << "pif ";
- game()->localplayer()->serialize_client_update(osstream);
- osstream << '\n';
- send(osstream.str());
+ FD_ZERO(&clientset);
+ FD_SET(fd(), &clientset);
+
+ game()->localplayer()->player_dirty = true;
}
void NetConnection::disconnect()
{
- TCPConnection::disconnect();
- FD_ZERO(&clientset);
+ if (connection_fd != -1) {
+ sendq.clear();
+ sendq.assign("disconnect\n");
+ transmit();
+
+ FD_ZERO(&clientset);
+ close(connection_fd);
+ }
+
+ connection_fd = -1;
+ connection_error = false;
+ connection_host.clear();
+ connection_port = 0;
}
bool NetConnection::has_messages() const
@@ -64,25 +122,41 @@ void NetConnection::retreive(std::string & message)
void NetConnection::receive()
{
// TODO: binary mode data transfer
- std::string datablock;
- TCPConnection::receive(datablock);
+ if (error() || invalid())
+ return;
+
+ ssize_t bytes_received;
+
+ memset(recvbuf, '\0', BLOCKSIZE);
+ bytes_received = ::recv(connection_fd, recvbuf, BLOCKSIZE-1, 0);
- if (error())
+ if (bytes_received == 0) {
+ con_print << "Disconnected.";
+ abort();
+ return;
+ } else if (bytes_received < 0) {
+ con_error << "Network receive() error!" << std::endl;
+ //perror("recv");
+ abort();
return;
- while (datablock.size() > 0) {
+ }
+
+ std::string datablock;
+ datablock.assign(recvbuf);
+
+ while (datablock.size()) {
// scan the datablock for enters
if (datablock[0] == '\n' || datablock[0] == '\r') {
- if (messageblock.size() > 0) {
+ if (messageblock.size() >= FRAMESIZE) {
+ con_warn << "Incoming message exceeds " << FRAMESIZE << " bytes!\n";
+ messageblock.clear();
+ } else if (messageblock.size()) {
recvq.push_back(messageblock);
+ //con_debug << "Incoming message '" << messageblock << "'" << std::endl;
messageblock.clear();
}
} else {
- if (messageblock.size() < net::FRAMESIZE) {
- messageblock.append(datablock.substr(0,1));
- } else {
- con_warn << "Network message exceeds " << net::FRAMESIZE << " bytes!" << std::endl;
- messageblock.clear();
- }
+ messageblock.append(datablock.substr(0,1));
}
datablock.erase(0,1);
}
@@ -97,22 +171,33 @@ void NetConnection::frame(float seconds)
fd_set readset = clientset;
int nb = select(fd()+1, &readset, NULL, NULL, &timeout);
- if (nb == 0)
+ if (nb == 0) {
return;
-
+ }
if (nb == -1) {
con_error << "Network error on select()" << std::endl;
//perror("select");
abort();
}
- if (FD_ISSET(this->fd(), &readset) && !error()) {
+ while (FD_ISSET(this->fd(), &readset) && !error()) {
receive();
+
while (has_messages()) {
std::string message;
retreive(message);
parse_incoming_message(message);
}
+
+ nb = select(fd()+1, &readset, NULL, NULL, &timeout);
+ if (nb == 0) {
+ return;
+ }
+ if (nb == -1) {
+ con_error << "Network error on select()" << std::endl;
+ //perror("select");
+ abort();
+ }
}
}
@@ -123,14 +208,32 @@ void NetConnection::send(std::string const &msg)
void NetConnection::transmit()
{
- while (sendq.size() && valid() && !error()) {
- TCPConnection::send(sendq.substr(0, net::FRAMESIZE-1));
- if (sendq.size() < net::FRAMESIZE) {
- sendq.clear();
- } else {
- sendq.erase(0, net::FRAMESIZE-1);
+
+ if (error() || invalid())
+ return;
+
+ if (sendq.size() > FRAMESIZE) {
+ con_warn << "Outgoing message exceeds " << FRAMESIZE << " bytes!\n";
+ //sendq.clear();
+ //return;
+ }
+
+ ssize_t bytes_sent = 0;
+
+ while (sendq.size()) {
+ bytes_sent = ::sendto(connection_fd, sendq.c_str(), sendq.size(), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
+ if (bytes_sent <= 0) {
+ con_error << "Network send() error!" << std::endl;
+ //perror("send");
+ abort();
+ return;
}
+
+ // assert (bytes_sent <= sendbuf.size());
+ sendq.erase(0, bytes_sent);
}
+
+ sendq.clear();
}
// parse incoming client messages