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
Log Message:
inventory_widget: don't fault on pgdn with only one item

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

File Contents

# User Rev Content
1 sf-pippijn 1.4 #include <cstring>
2 sf-pippijn 1.1
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 sf-pippijn 1.4 #include "adt/logs.h"
12    
13     #include "deliantra/communicator.h"
14     #include "deliantra/exception.h"
15    
16 sf-pippijn 1.1 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 sf-pippijn 1.3 //LOG ("net") << "data is ready\n";
69 sf-pippijn 1.1
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 sf-pippijn 1.3 throw exit_success ("EOF from server");
75 sf-pippijn 1.1 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 sf-pippijn 1.3 //LOG ("net") << "command length is ready: " << cmd_len << "\n";
85 sf-pippijn 1.1 if (response_len < cmd_len + 2)
86     break;
87    
88 sf-pippijn 1.3 //LOG ("net") << "command is ready; processing\n";
89 sf-pippijn 1.1 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 sf-pippijn 1.3 //LOG ("net") << response_len << " bytes left\n";
93 sf-pippijn 1.1 }
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     }