ETISS 0.8.0
Extendable Translating Instruction Set Simulator (version 0.8.0)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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
72using namespace etiss::plugin::gdb;
73
74UnixTCPGDBConnection::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}
113UnixTCPGDBConnection::~UnixTCPGDBConnection()
114{
115 if (valid_)
116 close(socket_);
117 if (active_valid_)
118 close(active_);
119}
120bool UnixTCPGDBConnection::available()
121{
122 return _available(false);
123}
124bool 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}
186std::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}
203bool 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