ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/cf.schmorp.de/dclient/src/backend/communicator/communicator.cpp
Revision: 1.3
Committed: Mon Oct 25 02:06:56 2010 UTC (15 years, 11 months ago) by sf-pippijn
Branch: MAIN
Changes since 1.2: +6 -5 lines
Log Message:
show content of open containers on the ground

File Contents

# Content
1 #include "deliantra/communicator.h"
2 #include "deliantra/exception.h"
3
4 #include "adt/logs.h"
5
6 #include <boost/lexical_cast.hpp>
7
8 #include <fcntl.h>
9 #include <netdb.h>
10 #include <netinet/in.h>
11 #include <sys/socket.h>
12 #include <unistd.h>
13
14 static std::string
15 strerror ()
16 {
17 return strerror (errno);
18 }
19
20 communicator::communicator (std::string const &server, std::string const &port)
21 : response_len (0)
22 , response { 0 }
23 {
24 LOG ("net") << "creating socket\n";
25 int sockfd = socket (AF_INET, SOCK_STREAM, 0);
26 if (sockfd == -1)
27 throw "socket: " + strerror ();
28
29 int portno = boost::lexical_cast<int> (port);
30
31 LOG ("net") << "resolving hostname: " << server << "\n";
32 hostent *serverent = gethostbyname (server.c_str ());
33 if (!serverent)
34 throw "gethostbyname: " + strerror ();
35
36 LOG ("net") << "connecting to: " << server << ":" << portno << "\n";
37 sockaddr_in addr = { 0 };
38 addr.sin_family = AF_INET;
39 memcpy (&addr.sin_addr.s_addr, serverent->h_addr, serverent->h_length);
40 addr.sin_port = htons (portno);
41 if (connect (sockfd, reinterpret_cast<sockaddr const *> (&addr), sizeof addr) == -1)
42 throw "connect: " + strerror ();
43
44 LOG ("net") << "setting socket to non-blocking\n";
45 int flags = fcntl (sockfd, F_GETFL, 0);
46 if (flags == -1)
47 flags = 0;
48 if (fcntl (sockfd, F_SETFL, flags | O_NONBLOCK) == -1)
49 throw "fcntl: " + strerror ();
50
51 LOG ("net") << "setting up read callback\n";
52 sock.set (sockfd, ev::READ);
53 sock.set<communicator, &communicator::read_cb> (this);
54 sock.start ();
55 }
56
57 void
58 communicator::set_packet_handler (interface::packet_handler &handler)
59 {
60 on = &handler;
61 }
62
63 void
64 communicator::read_cb (ev::io &w, int revents)
65 {
66 //LOG ("net") << "data is ready\n";
67
68 ssize_t readlen = read (w.fd, response + response_len, sizeof response - response_len);
69 if (readlen < 0)
70 throw "read: " + strerror ();
71 if (readlen == 0)
72 throw exit_success ("EOF from server");
73 response_len += readlen;
74
75 for (;;)
76 {
77 if (response_len < 2)
78 break;
79
80 unsigned int cmd_len = response[0] << 8 | response[1];
81
82 //LOG ("net") << "command length is ready: " << cmd_len << "\n";
83 if (response_len < cmd_len + 2)
84 break;
85
86 //LOG ("net") << "command is ready; processing\n";
87 on->receive (std::string (response + 2, response + 2 + cmd_len));
88 memmove (response, response + 2 + cmd_len, response_len - 2 - cmd_len);
89 response_len -= 2 + cmd_len;
90 //LOG ("net") << response_len << " bytes left\n";
91 }
92 }
93
94 void
95 communicator::send (std::string const &command)
96 {
97 LOG ("net") << "sending command: " << command << "\n";
98 write (sock.fd, &static_cast<uint16_t const &> (htons (command.length ())), 2);
99 if (write (sock.fd, command.data (), command.length ()) == -1)
100 throw "write: " + strerror ();
101 }