1 // Copyright (C) 2008 Ole Laursen
2 // Copyright (C) 2008 Ben Asselstine
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Library General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 #include "network-connection.h"
25 #include <sys/types.h>
28 #include "network-common.h"
31 event_helper(GConn* conn, GConnEvent* event, gpointer user_data)
33 static_cast<NetworkConnection *>(user_data)->gotConnectionEvent(conn, event);
37 NetworkConnection::NetworkConnection(_GConn *conn)
41 gnet_conn_set_callback(conn, &event_helper, this);
42 receiving_message = false;
43 gnet_conn_readn(conn, MESSAGE_SIZE_BYTES);
47 NetworkConnection::~NetworkConnection()
51 gnet_conn_delete(conn);
56 void NetworkConnection::connectToHost(std::string host, int port)
58 conn = gnet_conn_new(host.c_str(), port, &event_helper, this);
61 ; // FIXME: report error
63 gnet_conn_connect(conn);
64 gnet_conn_set_watch_error(conn, true);
65 gnet_conn_timeout(conn, 30 * 1000);
68 void NetworkConnection::sendFile(MessageType type, const std::string filename)
70 if (gnet_conn_is_connected(conn) == false)
72 FILE *fileptr = fopen (filename.c_str(), "r");
77 stat (filename.c_str(), &statbuf);
79 gchar buf[MESSAGE_SIZE_BYTES + MESSAGE_PREAMBLE_EXTRA_BYTES];
80 guint32 l = g_htonl(MESSAGE_PREAMBLE_EXTRA_BYTES + statbuf.st_size);
81 memcpy(buf, &l, MESSAGE_SIZE_BYTES);
82 buf[MESSAGE_SIZE_BYTES] = MESSAGE_PROTOCOL_VERSION;
83 buf[MESSAGE_SIZE_BYTES + 1] = type;
85 gnet_conn_write(conn, buf, MESSAGE_SIZE_BYTES + MESSAGE_PREAMBLE_EXTRA_BYTES);
87 std::cerr << "sending file " << type <<" of length " << MESSAGE_PREAMBLE_EXTRA_BYTES + statbuf.st_size << " to " << gnet_inetaddr_get_name(conn->inetaddr) << std::endl;
88 char *buffer = (char*) malloc (statbuf.st_size);
89 size_t bytesread = fread (buffer, 1, statbuf.st_size, fileptr);
91 gnet_conn_write(conn, const_cast<gchar *>(buffer), bytesread);
95 void NetworkConnection::send(MessageType type, const std::string &payload)
97 if (gnet_conn_is_connected(conn) == false)
100 gchar buf[MESSAGE_SIZE_BYTES + MESSAGE_PREAMBLE_EXTRA_BYTES];
101 guint32 l = g_htonl(MESSAGE_PREAMBLE_EXTRA_BYTES + payload.size());
102 memcpy(buf, &l, MESSAGE_SIZE_BYTES);
103 buf[MESSAGE_SIZE_BYTES] = MESSAGE_PROTOCOL_VERSION;
104 buf[MESSAGE_SIZE_BYTES + 1] = type;
106 gnet_conn_write(conn, buf, MESSAGE_SIZE_BYTES + MESSAGE_PREAMBLE_EXTRA_BYTES);
108 std::cerr << "sending message " << type <<" of length " << MESSAGE_PREAMBLE_EXTRA_BYTES + payload.size() << " to " << gnet_inetaddr_get_name(conn->inetaddr) << std::endl;
111 gnet_conn_write(conn, const_cast<gchar *>(payload.data()), payload.size());
114 void NetworkConnection::gotConnectionEvent(GConn* conn, GConnEvent* event)
118 case GNET_CONN_CONNECT:
119 gnet_conn_timeout(conn, 0); // stop timeout
120 receiving_message = false;
121 gnet_conn_readn(conn, MESSAGE_SIZE_BYTES);
126 if (receiving_message)
128 if (event->length < 2)
130 // misbehaving server
131 gnet_conn_disconnect(conn);
135 // protocol version is ignored for now
136 //int protocol_version = event->buffer[0];
137 MessageType type = MessageType(event->buffer[1]);
139 got_message.emit(type, std::string(event->buffer + MESSAGE_PREAMBLE_EXTRA_BYTES,
140 event->length - MESSAGE_PREAMBLE_EXTRA_BYTES));
141 receiving_message = false;
142 gnet_conn_readn(conn, MESSAGE_SIZE_BYTES);
146 g_assert(event->length == MESSAGE_SIZE_BYTES);
148 memcpy(&val, event->buffer, 4);
149 int message_size = g_ntohl(val);
151 std::cerr << "going to read length " << message_size << std::endl;
152 receiving_message = true;
153 gnet_conn_readn(conn, message_size);
154 connection_received_data.emit();
158 case GNET_CONN_WRITE:
161 case GNET_CONN_CLOSE:
162 case GNET_CONN_TIMEOUT:
163 case GNET_CONN_ERROR:
164 connection_lost.emit();
165 gnet_conn_delete(conn);
169 g_assert_not_reached ();