ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/cf.schmorp.de/dclient/src/backend/communicator/communicator.cpp
Revision: 1.4
Committed: Mon Feb 7 19:18:44 2011 UTC (15 years, 8 months ago) by sf-pippijn
Branch: MAIN
CVS Tags: HEAD
Changes since 1.3: +6 -4 lines
Error occurred while calculating annotation data.
Log Message:
inventory_widget: don't fault on pgdn with only one item

by Jonathan Neuschäfer <j.neuschaefer@gmx.net>

File Contents

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