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

# User Rev Content
1 sf-pippijn 1.1 #include "deliantra/communicator.h"
2 sf-pippijn 1.3 #include "deliantra/exception.h"
3 sf-pippijn 1.1
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 sf-pippijn 1.3 //LOG ("net") << "data is ready\n";
67 sf-pippijn 1.1
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 sf-pippijn 1.3 throw exit_success ("EOF from server");
73 sf-pippijn 1.1 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 sf-pippijn 1.3 //LOG ("net") << "command length is ready: " << cmd_len << "\n";
83 sf-pippijn 1.1 if (response_len < cmd_len + 2)
84     break;
85    
86 sf-pippijn 1.3 //LOG ("net") << "command is ready; processing\n";
87 sf-pippijn 1.1 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 sf-pippijn 1.3 //LOG ("net") << response_len << " bytes left\n";
91 sf-pippijn 1.1 }
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     }