ETISS 0.8.0
Extendable Translating Instruction Set Simulator (version 0.8.0)
UnixTCPGDBConnection.cpp
Go to the documentation of this file.
1 
54 
55 #if ETISS_USE_POSIX_SOCKET
56 
57 #include <iostream>
58 
59 #include <errno.h>
60 #include <netinet/in.h>
61 #include <netinet/tcp.h>
62 #include <string.h>
63 #include <sys/socket.h>
64 #include <sys/types.h>
65 #include <unistd.h>
66 
67 #ifndef SOCK_NONBLOCK
68 #include <fcntl.h>
69 #define SOCK_NONBLOCK O_NONBLOCK
70 #endif
71 
72 using namespace etiss::plugin::gdb;
73 
74 UnixTCPGDBConnection::UnixTCPGDBConnection(unsigned port)
75 {
76  valid_ = true;
77  buffer_pos_ = 0;
78  socket_ = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
79  active_valid_ = false;
80  // check socket
81  if (socket_ < 0)
82  {
83  valid_ = false;
84  std::cout << "ERROR: failed to create TCP socket (ipv4)" << std::endl;
85  std::cout << "\t" << strerror(errno) << std::endl;
86  }
87  // configure socket
88  int flag = 1;
89  setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int)); // disable nagle
90  flag = 1;
91  setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, (char *)&flag,
92  sizeof(int)); // allow to use port immediatly after this program finished
93  // bind socket
94  if (valid_)
95  {
96  struct sockaddr_in addr;
97  addr.sin_family = AF_INET;
98  addr.sin_addr.s_addr = INADDR_ANY;
99  addr.sin_port = htons(port);
100  if (bind(socket_, (struct sockaddr *)&addr, sizeof(addr)) < 0)
101  {
102  valid_ = false;
103  std::cout << "ERROR: failed to bind TCP socket (ipv4) to port " << port << std::endl;
104  std::cout << "\t" << strerror(errno) << std::endl;
105  }
106  }
107  // make passive
108  if (valid_)
109  {
110  listen(socket_, 1);
111  }
112 }
113 UnixTCPGDBConnection::~UnixTCPGDBConnection()
114 {
115  if (valid_)
116  close(socket_);
117  if (active_valid_)
118  close(active_);
119 }
120 bool UnixTCPGDBConnection::available()
121 {
122  return _available(false);
123 }
124 bool UnixTCPGDBConnection::_available(bool block)
125 {
126  if (buffer_pos_ > 0)
127  return true;
128  if (!valid_ && !active_valid_)
129  return false;
130  // accept new socket
131  if (!active_valid_ && valid_)
132  {
133  int cur = accept(socket_, 0, 0);
134  if (cur >= 0)
135  {
136  active_ = cur;
137  active_valid_ = true;
138  // configure socket
139  int flag = 1;
140  setsockopt(cur, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));
141  }
142  }
143  if (active_valid_)
144  {
145  if (valid_)
146  {
147  int deny = accept(socket_, 0, 0);
148  if (deny >= 0)
149  {
150  close(deny);
151  }
152  }
153  ssize_t len = recv(active_, (void *)(buffer_ + buffer_pos_), 1024 - buffer_pos_, block ? 0 : MSG_DONTWAIT);
154  if (len > 0)
155  {
156  for (unsigned i = buffer_pos_; i < (unsigned)(buffer_pos_ + len); i++)
157  {
158  if (buffer_[i] == 243 || buffer_[i] == 3)
159  { // BREAK character // NOTE: usually ctrl-C is sent
160  for (int j = i + 1; j < buffer_pos_ + len; j++)
161  {
162  buffer_[j - 1] = buffer_[j];
163  }
164  len -= 1;
165  pending_break_ = true;
166  // no "break;" in case multiple brk chars have been sent
167  }
168  }
169  buffer_pos_ += len;
170  }
171  else if (len == 0)
172  { // eof
173  close(active_);
174  active_valid_ = false;
175  }
176  else if (errno != EAGAIN && errno != EWOULDBLOCK)
177  {
178  std::cout << "ERROR: gdb socket failed" << std::endl;
179  std::cout << "\t" << strerror(errno) << std::endl;
180  close(active_);
181  active_valid_ = false;
182  }
183  }
184  return buffer_pos_ > 0;
185 }
186 std::string UnixTCPGDBConnection::rcv()
187 {
188  if (buffer_pos_ == 0)
189  _available(true);
190  std::string ret;
191  if (buffer_pos_ > 0)
192  {
193  for (unsigned i = 0; i < buffer_pos_; i++)
194  {
195  ret.push_back((char)buffer_[i]);
196  }
197  buffer_pos_ = 0;
198  }
199  // if (ret.length()>0)
200  // std::cout << "\""<< ret<< "\""<< std::endl;
201  return ret;
202 }
203 bool UnixTCPGDBConnection::snd(std::string answer)
204 {
205  if (active_valid_)
206  {
207  unsigned pos = 0;
208  // std::cout << "\""<< answer<< "\""<< std::endl;
209  while (pos < answer.length())
210  {
211  ssize_t len = write(active_, answer.c_str() + pos, answer.length() - pos);
212  if (len < 0)
213  {
214  if (len != EAGAIN && len != EWOULDBLOCK)
215  {
216  close(active_);
217  active_valid_ = false;
218  return false;
219  }
220  }
221  else
222  {
223  pos += len;
224  }
225  }
226  return true;
227  }
228  else
229  {
230  available();
231  return false;
232  }
233 }
234 
235 #endif // ETISS_USE_POSIX_SOCKET
char flag
Definition: 386-GCC.h:75