OpenCores
URL https://opencores.org/ocsvn/riscv_vhdl/riscv_vhdl/trunk

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [debugger/] [src/] [libdbg64g/] [services/] [debug/] [udp_dbglink.cpp] - Blame information for rev 5

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 5 sergeykhbr
/**
2
 * @file
3
 * @copyright  Copyright 2017 GNSS Sensor Ltd. All right reserved.
4
 * @author     Sergey Khabarov - sergeykhbr@gmail.com
5
 * @brief      UDP transport level implementation.
6
 */
7
 
8
#include "api_core.h"
9
#include "udp_dbglink.h"
10
 
11
namespace debugger {
12
 
13
/** Class registration in the Core */
14
REGISTER_CLASS(UdpService)
15
 
16
UdpService::UdpService(const char *name)
17
    : IService(name) {
18
    registerInterface(static_cast<ILink *>(this));
19
    registerAttribute("Timeout", &timeout_);
20
    registerAttribute("BlockingMode", &blockmode_);
21
    registerAttribute("HostIP", &hostIP_);
22
    registerAttribute("BoardIP", &boardIP_);
23
 
24
    timeout_.make_int64(0);
25
    blockmode_.make_boolean(true);
26
    hostIP_.make_string("192.168.0.53");
27
    boardIP_.make_string("192.168.0.51");
28
}
29
 
30
UdpService::~UdpService() {
31
    closeDatagramSocket();
32
}
33
 
34
void UdpService::postinitService() {
35
    createDatagramSocket();
36
    // define hardcoded remote address:
37
    remote_sockaddr_ipv4_ = sockaddr_ipv4_;
38
    remote_sockaddr_ipv4_.sin_addr.s_addr = inet_addr(boardIP_.to_string());
39
 
40
    if (timeout_.to_int64()) {
41
        struct timeval tv;
42
#if defined(_WIN32) || defined(__CYGWIN__)
43
        /** On windows timeout of the setsockopt() function is the DWORD
44
         * size variable in msec, so we use only the first field in timeval
45
         * struct and directly assgign argument.
46
         */
47
        tv.tv_usec = 0;
48
        tv.tv_sec = static_cast<long>(timeout_.to_int64());
49
#else
50
        tv.tv_usec = (timeout_.to_int64() % 1000) * 1000;
51
        tv.tv_sec = static_cast<long>(timeout_.to_int64()/1000);
52
#endif
53
 
54
        setsockopt(hsock_, SOL_SOCKET, SO_RCVTIMEO,
55
                            (char *)&tv, sizeof(struct timeval));
56
    }
57
 
58
    /** By default socket was created with Blocking mode */
59
    if (!blockmode_.to_bool()) {
60
        setBlockingMode(false);
61
    }
62
}
63
 
64
int UdpService::createDatagramSocket() {
65
    char hostName[256];
66
    if (gethostname(hostName, sizeof(hostName)) < 0) {
67
        return -1;
68
    }
69
 
70
    struct addrinfo hints;
71
    memset(&hints, 0, sizeof(hints));
72
    hints.ai_family = AF_UNSPEC;
73
    hints.ai_socktype = SOCK_STREAM;
74
    hints.ai_protocol = IPPROTO_TCP;
75
 
76
    /**
77
     * Check availability of IPv4 address assigned via attribute 'hostIP'.
78
     * If it woudn't be found use the last avaialble IP address.
79
     */
80
    bool host_ip_found = false;
81
    int retval;
82
    struct addrinfo *result = NULL;
83
    struct addrinfo *ptr = NULL;
84
    retval = getaddrinfo(hostName, "0", &hints, &result);
85
    if (retval != 0) {
86
        return -1;
87
    }
88
 
89
    for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {
90
        // Find only IPV4 address, ignore others.
91
        if (ptr->ai_family != AF_INET) {
92
            continue;
93
        }
94
        sockaddr_ipv4_ = *((struct sockaddr_in *)ptr->ai_addr);
95
        RISCV_sprintf(sockaddr_ipv4_str_, sizeof(sockaddr_ipv4_str_),
96
                    "%s", inet_ntoa(sockaddr_ipv4_.sin_addr));
97
 
98
        if (strcmp(inet_ntoa(sockaddr_ipv4_.sin_addr),
99
                   hostIP_.to_string()) == 0) {
100
            host_ip_found = true;
101
            break;
102
        }
103
    }
104
 
105
    if (!host_ip_found) {
106
        RISCV_info("Selected IPv4 %s", inet_ntoa(sockaddr_ipv4_.sin_addr));
107
    } else {
108
#if 1
109
        /** jrkk proposal to hardcode IP address in a such way. No difference. */
110
        memset(&sockaddr_ipv4_, 0, sizeof (sockaddr_ipv4_));
111
        sockaddr_ipv4_.sin_family = AF_INET;
112
        inet_pton(AF_INET, hostIP_.to_string(), &(sockaddr_ipv4_.sin_addr));
113
#endif
114
    }
115
 
116
    hsock_ = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
117
    if (hsock_ < 0) {
118
        RISCV_error("%s", "Error: socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)");
119
        return -1;
120
    }
121
 
122
    int res = bind(hsock_, (struct sockaddr *)&sockaddr_ipv4_,
123
                              sizeof(sockaddr_ipv4_));
124
    if (res != 0) {
125
        RISCV_error("Error: bind(hsock_, \"%s\", ...)", hostIP_.to_string());
126
        return -1;
127
    }
128
 
129
    addr_size_t addr_sz = sizeof(sockaddr_ipv4_);
130
    res = getsockname(hsock_, (struct sockaddr *)&sockaddr_ipv4_, &addr_sz);
131
    sockaddr_ipv4_port_ = ntohs(sockaddr_ipv4_.sin_port);
132
 
133
    RISCV_info("\tIPv4 address %s:%d . . . opened",
134
                sockaddr_ipv4_str_, sockaddr_ipv4_port_);
135
 
136
    return 0;
137
}
138
 
139
void UdpService::closeDatagramSocket() {
140
    if (hsock_ < 0)
141
        return;
142
 
143
#if defined(_WIN32) || defined(__CYGWIN__)
144
    closesocket(hsock_);
145
#else
146
    shutdown(hsock_, SHUT_RDWR);
147
    close(hsock_);
148
#endif
149
    hsock_ = -1;
150
}
151
 
152
void UdpService::getConnectionSettings(AttributeType *settings) {
153
    settings->make_dict();
154
    (*settings)["IP"] = AttributeType(inet_ntoa(sockaddr_ipv4_.sin_addr));
155
    (*settings)["Port"] = AttributeType(Attr_UInteger,
156
                static_cast<uint64_t>(sockaddr_ipv4_.sin_port));
157
}
158
 
159
void UdpService::setConnectionSettings(const AttributeType *target) {
160
    if (!target->is_dict()) {
161
        return;
162
    }
163
    remote_sockaddr_ipv4_.sin_addr.s_addr =
164
        inet_addr((*target)["IP"].to_string());
165
    remote_sockaddr_ipv4_.sin_port =
166
        static_cast<uint16_t>((*target)["Port"].to_uint64());
167
}
168
 
169
bool UdpService::setBlockingMode(bool mode) {
170
    int ret;
171
#if defined(_WIN32) || defined(__CYGWIN__)
172
    u_long arg = mode ? 0 : 1;
173
    ret = ioctlsocket(hsock_, FIONBIO, &arg);
174
#else
175
    int flags = fcntl(hsock_, F_GETFL, 0);
176
    if (flags < 0) {
177
        return false;
178
    }
179
    flags = mode ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
180
    ret = fcntl(hsock_, F_SETFL, flags);
181
#endif
182
    if (ret == 0) {
183
        // success
184
        blockmode_.make_boolean(mode);
185
        return true;
186
    }
187
    return false;
188
}
189
 
190
int UdpService::sendData(const uint8_t *msg, int len) {
191
    int tx_bytes = sendto(hsock_, reinterpret_cast<const char *>(msg), len, 0,
192
                  reinterpret_cast<struct sockaddr *>(&remote_sockaddr_ipv4_),
193
                  static_cast<int>(sizeof(remote_sockaddr_ipv4_)));
194
 
195
    if (tx_bytes < 0) {
196
#if defined(_WIN32) || defined(__CYGWIN__)
197
        RISCV_error("sendto() failed with error: %d\n", WSAGetLastError());
198
#else
199
        RISCV_error("sendto() failed\n", NULL);
200
#endif
201
        return 1;
202
    } else if (logLevel_.to_int() >= LOG_DEBUG) {
203
        char dbg[1024];
204
        int pos = RISCV_sprintf(dbg, sizeof(dbg), "send  %d bytes to %s:%d: ",
205
                                tx_bytes,
206
                                inet_ntoa(remote_sockaddr_ipv4_.sin_addr),
207
                                ntohs(remote_sockaddr_ipv4_.sin_port));
208
 
209
        if (tx_bytes < 64) {
210
            for (int i = 0; i < len; i++) {
211
                pos += RISCV_sprintf(&dbg[pos], sizeof(dbg) - pos,
212
                                                "%02x", msg[i] & 0xFF);
213
            }
214
        }
215
        RISCV_debug("%s", dbg);
216
    }
217
    return tx_bytes;
218
}
219
 
220
int UdpService::readData(const uint8_t *buf, int maxlen) {
221
    int sockerr;
222
    addr_size_t sockerr_len = sizeof(sockerr);
223
    addr_size_t addr_sz = sizeof(sockaddr_ipv4_);
224
 
225
    int res = recvfrom(hsock_, rcvbuf, sizeof(rcvbuf),
226
                        0, (struct sockaddr *)&sockaddr_ipv4_, &addr_sz);
227
    getsockopt(hsock_, SOL_SOCKET, SO_ERROR,
228
                            (char *)&sockerr, &sockerr_len);
229
 
230
    if (res < 0 && sockerr < 0) {
231
        RISCV_error("Socket error %x", sockerr);
232
        res = -1;
233
    } else if (res < 0 && sockerr == 0) {
234
        // Timeout:
235
        res = 0;
236
    } else if (res > 0) {
237
        if (maxlen < res) {
238
            res = maxlen;
239
            RISCV_error("Receiver's buffer overflow maxlen = %d", maxlen);
240
        }
241
        memcpy(const_cast<uint8_t *>(buf), rcvbuf, res);
242
 
243
        if (logLevel_.to_int() >= LOG_DEBUG) {
244
            char dbg[1024];
245
            int pos = RISCV_sprintf(dbg, sizeof(dbg),
246
                                    "received  %d Bytes: ", res);
247
            if (res < 64) {
248
                for (int i = 0; i < res; i++) {
249
                    pos += RISCV_sprintf(&dbg[pos], sizeof(dbg) - pos,
250
                                        "%02x", rcvbuf[i] & 0xFF);
251
                }
252
            }
253
            RISCV_debug("%s", dbg);
254
        }
255
    }
256
    return res;
257
}
258
 
259
}  // namespace debugger

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.