ETISS 0.11.2
ExtendableTranslatingInstructionSetSimulator(version0.11.2)
Loading...
Searching...
No Matches
UnixTCPGDBConnection.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: BSD-3-Clause
2//
3// This file is part of ETISS. It is licensed under the BSD 3-Clause License; you may not use this file except in
4// compliance with the License. You should have received a copy of the license along with this project. If not, see the
5// LICENSE file.
16
17#if ETISS_USE_POSIX_SOCKET
18
19#include <iostream>
20
21#include <errno.h>
22#include <netinet/in.h>
23#include <netinet/tcp.h>
24#include <string.h>
25#include <sys/socket.h>
26#include <sys/types.h>
27#include <unistd.h>
28
29#ifndef SOCK_NONBLOCK
30#include <fcntl.h>
31#define SOCK_NONBLOCK O_NONBLOCK
32#endif
33
34using namespace etiss::plugin::gdb;
35
36UnixTCPGDBConnection::UnixTCPGDBConnection(unsigned port)
37{
38 valid_ = true;
39 buffer_pos_ = 0;
40 socket_ = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
41 active_valid_ = false;
42 // check socket
43 if (socket_ < 0)
44 {
45 valid_ = false;
46 std::cout << "ERROR: failed to create TCP socket (ipv4)" << std::endl;
47 std::cout << "\t" << strerror(errno) << std::endl;
48 }
49 // configure socket
50 int flag = 1;
51 setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int)); // disable nagle
52 flag = 1;
53 setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, (char *)&flag,
54 sizeof(int)); // allow to use port immediatly after this program finished
55 // bind socket
56 if (valid_)
57 {
58 struct sockaddr_in addr;
59 addr.sin_family = AF_INET;
60 addr.sin_addr.s_addr = INADDR_ANY;
61 addr.sin_port = htons(port);
62 if (bind(socket_, (struct sockaddr *)&addr, sizeof(addr)) < 0)
63 {
64 valid_ = false;
65 std::cout << "ERROR: failed to bind TCP socket (ipv4) to port " << port << std::endl;
66 std::cout << "\t" << strerror(errno) << std::endl;
67 }
68 }
69 // make passive
70 if (valid_)
71 {
72 listen(socket_, 1);
73 }
74}
75UnixTCPGDBConnection::~UnixTCPGDBConnection()
76{
77 if (valid_)
78 close(socket_);
79 if (active_valid_)
80 close(active_);
81}
82bool UnixTCPGDBConnection::available()
83{
84 return _available(false);
85}
86bool UnixTCPGDBConnection::_available(bool block)
87{
88 if (buffer_pos_ > 0)
89 return true;
90 if (!valid_ && !active_valid_)
91 return false;
92 // accept new socket
93 if (!active_valid_ && valid_)
94 {
95 int cur = accept(socket_, 0, 0);
96 if (cur >= 0)
97 {
98 active_ = cur;
99 active_valid_ = true;
100 // configure socket
101 int flag = 1;
102 setsockopt(cur, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));
103 }
104 }
105 if (active_valid_)
106 {
107 if (valid_)
108 {
109 int deny = accept(socket_, 0, 0);
110 if (deny >= 0)
111 {
112 close(deny);
113 }
114 }
115 ssize_t len = recv(active_, (void *)(buffer_ + buffer_pos_), 1024 - buffer_pos_, block ? 0 : MSG_DONTWAIT);
116 if (len > 0)
117 {
118 for (unsigned i = buffer_pos_; i < (unsigned)(buffer_pos_ + len); i++)
119 {
120 if (buffer_[i] == 243 || buffer_[i] == 3)
121 { // BREAK character // NOTE: usually ctrl-C is sent
122 for (int j = i + 1; j < buffer_pos_ + len; j++)
123 {
124 buffer_[j - 1] = buffer_[j];
125 }
126 len -= 1;
127 pending_break_ = true;
128 // no "break;" in case multiple brk chars have been sent
129 }
130 }
131 buffer_pos_ += len;
132 }
133 else if (len == 0)
134 { // eof
135 close(active_);
136 active_valid_ = false;
137 }
138 else if (errno != EAGAIN && errno != EWOULDBLOCK)
139 {
140 std::cout << "ERROR: gdb socket failed" << std::endl;
141 std::cout << "\t" << strerror(errno) << std::endl;
142 close(active_);
143 active_valid_ = false;
144 }
145 }
146 return buffer_pos_ > 0;
147}
148std::string UnixTCPGDBConnection::rcv()
149{
150 if (buffer_pos_ == 0)
151 _available(true);
152 std::string ret;
153 if (buffer_pos_ > 0)
154 {
155 for (unsigned i = 0; i < buffer_pos_; i++)
156 {
157 ret.push_back((char)buffer_[i]);
158 }
159 buffer_pos_ = 0;
160 }
161 // if (ret.length()>0)
162 // std::cout << "\""<< ret<< "\""<< std::endl;
163 return ret;
164}
165bool UnixTCPGDBConnection::snd(std::string answer)
166{
167 if (active_valid_)
168 {
169 unsigned pos = 0;
170 // std::cout << "\""<< answer<< "\""<< std::endl;
171 while (pos < answer.length())
172 {
173 ssize_t len = write(active_, answer.c_str() + pos, answer.length() - pos);
174 if (len < 0)
175 {
176 if (len != EAGAIN && len != EWOULDBLOCK)
177 {
178 close(active_);
179 active_valid_ = false;
180 return false;
181 }
182 }
183 else
184 {
185 pos += len;
186 }
187 }
188 return true;
189 }
190 else
191 {
192 available();
193 return false;
194 }
195}
196
197#endif // ETISS_USE_POSIX_SOCKET