bool create_notification_pipe(LIBEVENT_THREAD *me) { int j; if (evutil_socketpair(SOCKETPAIR_AF, SOCK_STREAM, 0, (void*)me->notify) == SOCKET_ERROR) { log_socket_error(EXTENSION_LOG_WARNING, NULL, "Can't create notify pipe: %s"); return false; } for (j = 0; j < 2; ++j) { int flags = 1; setsockopt(me->notify[j], IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags)); setsockopt(me->notify[j], SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags)); if (evutil_make_socket_nonblocking(me->notify[j]) == -1) { log_socket_error(EXTENSION_LOG_WARNING, NULL, "Failed to enable non-blocking: %s"); return false; } } return true; }
/* Non-blocking poll. Enter the debugger loop if a message is received. */ void gdbstub_recv(void) { int ret, on; if (!socket_fd) { ret = accept(listen_socket_fd, NULL, NULL); if (ret == -1) return; socket_fd = ret; /* Disable Nagle for low latency */ on = 1; #ifdef __MINGW32__ ret = setsockopt(socket_fd, IPPROTO_TCP, TCP_NODELAY, (const char *)&on, sizeof(on)); #else ret = setsockopt(socket_fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)); #endif if (ret == -1) log_socket_error("setsockopt(TCP_NODELAY) failed for GDB stub socket"); /* Interface with Ndless */ if (ndls_is_installed()) armloader_load_snippet(SNIPPET_ndls_debug_alloc, NULL, 0, gdb_connect_ndls_cb); gdb_connected = true; puts("GDB connected."); return; } fd_set rfds; FD_ZERO(&rfds); FD_SET((unsigned)socket_fd, &rfds); ret = select(socket_fd + 1, &rfds, NULL, NULL, &(struct timeval) {0, 0});
/* Read exactly n bytes from the DAC connection socket. * * This reads exactly len bytes into buf. Data is read in chunks from the * OS socket library and buffered in the dac_conn_t structure; individual * sections are then copied out. * * Returns 0 on success, -1 on error. If an error occurs, this will call * log_socket_error() to log the issue. The error code is also available * from WSAGetLastError(). */ int dac_read_bytes(dac_t *d, char *buf, int len) { while (d->conn.size < len) { // Wait for readability. int res = wait_for_activity(d, DEFAULT_TIMEOUT); if (res < 0) { closesocket(d->conn.sock); d->conn.sock = INVALID_SOCKET; return -1; } else if (res == 0) { flogd(d, "!! Read from DAC timed out.\n"); closesocket(d->conn.sock); d->conn.sock = INVALID_SOCKET; return -1; } res = recv(d->conn.sock, d->conn.buf + d->conn.size, len - d->conn.size, 0); if (res == 0 || res == SOCKET_ERROR) { log_socket_error(d, "recv"); return -1; } d->conn.size += res; } memcpy(buf, d->conn.buf, len); if (d->conn.size > len) { memmove(d->conn.buf, d->conn.buf + len, d->conn.size - len); } d->conn.size -= len; return 0; }
static void drain_notification_channel(evutil_socket_t fd) { int nread; while ((nread = recv(fd, devnull, sizeof(devnull), 0)) == (int)sizeof(devnull)) { /* empty */ } if (nread == -1) { log_socket_error(EXTENSION_LOG_WARNING, NULL, "Can't read from libevent pipe: %s"); } }
static void gdbstub_bind(int port) { struct sockaddr_in sockaddr; int r; #ifdef __MINGW32__ WORD wVersionRequested = MAKEWORD(2, 0); WSADATA wsaData; if (WSAStartup(wVersionRequested, &wsaData)) { log_socket_error("WSAStartup failed"); exit(1); } #endif listen_socket_fd = socket(PF_INET, SOCK_STREAM, 0); if (listen_socket_fd == -1) { log_socket_error("Failed to create GDB stub socket"); exit(1); } #ifdef __MINGW32__ u_long mode = 1; ioctlsocket(listen_socket_fd, FIONBIO, &mode); #else ret = fcntl(listen_socket_fd, F_GETFL, 0); fcntl(listen_socket_fd, F_SETFL, ret | O_NONBLOCK); #endif memset (&sockaddr, '\000', sizeof sockaddr); sockaddr.sin_family = AF_INET; sockaddr.sin_port = htons(port); sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); r = bind(listen_socket_fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)); if (r == -1) { log_socket_error("Failed to bind GDB stub socket. Check that nspire_emu is not already running"); exit(1); } r = listen(listen_socket_fd, 0); if (r == -1) { log_socket_error("Failed to listen on GDB stub socket"); } }
int tcp_connect(const char *host, int port) { SOCKET sockfd; struct sockaddr_in servaddr; char ipbuf[16]; if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { log_socket_error(L_ERROR|L_CONS, "[tcp_connect] " "socket() failed for %s, %d", host, port); return -1; } memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(port); servaddr.sin_addr.s_addr = ip_getaddr(host); if(servaddr.sin_addr.s_addr == htonl(INADDR_NONE)) { radlog(L_ERROR|L_CONS, "[tcp_connect] " "invalid host %s", host); closesocket(sockfd); return -1; } if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) == SOCKET_ERROR) { log_socket_error(L_ERROR|L_CONS, "[tcp_connect] " "connect() failed for %s (%s), %d", host, ip_ntoa(ipbuf, servaddr.sin_addr.s_addr), port); closesocket(sockfd); return -1; } DEBUG("[tcp_connect] %s (%s:%d), got sockfd(%d)", host, ip_ntoa(ipbuf, servaddr.sin_addr.s_addr), port, sockfd); return sockfd; }
/* Wait for writability. */ int wait_for_write(dac_t *d, int usec) { fd_set set; FD_ZERO(&set); FD_SET(d->conn.sock, &set); struct timeval time; time.tv_sec = usec / 1000000; time.tv_usec = usec % 1000000; int res = select(0, NULL, &set, &set, &time); if (res == SOCKET_ERROR) { log_socket_error(d, "select"); return -1; } return res; }
static void flush_out_buffer(void) { char *p = sockbuf; while (p != sockbufptr) { int n = send(socket_fd, p, sockbufptr-p, 0); if (n == -1) { #ifdef __MINGW32__ if (WSAGetLastError() == WSAEWOULDBLOCK) #else if (errno == EAGAIN) #endif continue; // not ready to send else { log_socket_error("Failed to send to GDB stub socket"); break; } } p += n; } sockbufptr = sockbuf; }
int dac_sendall(dac_t *d, const char *data, int len) { do { int res = wait_for_write(d, 1500000); if (res < 0) { return -1; } else if (res == 0) { trace(d, "write timed out\n"); } res = send(d->conn.sock, data, len, 0); if (res == SOCKET_ERROR) { log_socket_error(d, "send"); return -1; } len -= res; data += res; } while (len); return 0; }
/* Initialize a dac_conn_t and connect to the DAC. * * On success, return 0. */ int dac_connect(dac_t *d, const char *host, const char *port) { dac_conn_t *conn = &d->conn; ZeroMemory(conn, sizeof(d->conn)); // Look up the server address struct addrinfo *result = NULL, *ptr = NULL, hints; ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; trace(d, "Calling getaddrinfo: \"%s\", \"%s\"\n", host, port); int res = getaddrinfo(host, port, &hints, &result); if (res != 0) { trace(d, "getaddrinfo failed: %d\n", res); return -1; } // Create a SOCKET ptr = result; conn->sock = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); if (conn->sock == INVALID_SOCKET) { log_socket_error(d, "socket"); freeaddrinfo(result); return -1; } unsigned long nonblocking = 1; ioctlsocket(conn->sock, FIONBIO, &nonblocking); memset(&conn->udp_target, 0, sizeof(conn->udp_target)); conn->udp_target.sin_family = AF_INET; conn->udp_target.sin_addr.s_addr = ((struct sockaddr_in *)(ptr->ai_addr))->sin_addr.s_addr; conn->udp_target.sin_port = htons(60000); // Connect to host. Because the socket is nonblocking, this // will always return WSAEWOULDBLOCK. connect(conn->sock, ptr->ai_addr, (int)ptr->ai_addrlen); freeaddrinfo(result); if (WSAGetLastError() != WSAEWOULDBLOCK) { log_socket_error(d, "connect"); closesocket(conn->sock); conn->sock = INVALID_SOCKET; return -1; } // Wait for connection. fd_set set; FD_ZERO(&set); FD_SET(conn->sock, &set); struct timeval time; time.tv_sec = 0; time.tv_usec = DEFAULT_TIMEOUT; res = select(0, &set, &set, &set, &time); if (res == SOCKET_ERROR) { log_socket_error(d, "select"); closesocket(conn->sock); conn->sock = INVALID_SOCKET; return -1; } else if (res == 0) { trace(d, "Connection to %s timed out.\n", host); closesocket(conn->sock); conn->sock = INVALID_SOCKET; return -1; } // See if we have *actually* connected int error; int len = sizeof(error); if (getsockopt(conn->sock, SOL_SOCKET, SO_ERROR, (char *)&error, &len) == SOCKET_ERROR) { log_socket_error(d, "getsockopt"); closesocket(conn->sock); conn->sock = INVALID_SOCKET; return -1; } if (error) { WSASetLastError(error); log_socket_error(d, "connect"); closesocket(conn->sock); conn->sock = INVALID_SOCKET; return -1; } BOOL ndelay = 1; res = setsockopt(conn->sock, IPPROTO_TCP, TCP_NODELAY, (char *)&ndelay, sizeof(ndelay)); if (res == SOCKET_ERROR) { log_socket_error(d, "setsockopt TCP_NODELAY"); closesocket(conn->sock); conn->sock = INVALID_SOCKET; return -1; } trace(d, "Connected.\n"); // Create socket for OSC conn->udp_sock = socket(AF_INET, SOCK_DGRAM, 0); if (conn->udp_sock == INVALID_SOCKET) { log_socket_error(d, "socket(AF_INET, SOCK_DRGAM)"); } else { res = connect(conn->udp_sock, (struct sockaddr *)&conn->udp_target, sizeof(conn->udp_target)); if (res == SOCKET_ERROR) { log_socket_error(d, "connect(udp_sock)"); } } nonblocking = 1; ioctlsocket(conn->udp_sock, FIONBIO, &nonblocking); // After we connect, the host will send an initial status response. dac_read_resp(d, DEFAULT_TIMEOUT); dac_dump_resp(d); char c = 'p'; dac_sendall(d, &c, 1); dac_read_resp(d, DEFAULT_TIMEOUT); dac_dump_resp(d); if (d->sw_revision >= 2) { c = 'v'; dac_sendall(d, &c, 1); res = dac_read_bytes(d, d->version, sizeof(d->version)); if (res < 0) return res; trace(d, "DAC version: %.*s\n", sizeof(d->version), d->version); } else { memset(d->version, 0, sizeof(d->version)); trace(d, "DAC version old!\n"); } return 0; }
/* Initialize a dac_conn_t and connect to the DAC. * * On success, return 0. */ int dac_connect(dac_t *d, const char *host, const char *port) { dac_conn_t *conn = &d->conn; ZeroMemory(conn, sizeof(d->conn)); // Look up the server address struct addrinfo *result = NULL, *ptr = NULL, hints; ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; flogd(d, "Calling getaddrinfo: \"%s\", \"%s\"\n", host, port); int res = getaddrinfo(host, port, &hints, &result); if (res != 0) { flogd(d, "getaddrinfo failed: %d\n", res); return -1; } // Create a SOCKET ptr = result; conn->sock = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); if (conn->sock == INVALID_SOCKET) { log_socket_error(d, "socket"); freeaddrinfo(result); return -1; } unsigned long nonblocking = 1; ioctlsocket(conn->sock, FIONBIO, &nonblocking); // Connect to host. Because the socket is nonblocking, this // will always return WSAEWOULDBLOCK. connect(conn->sock, ptr->ai_addr, (int)ptr->ai_addrlen); freeaddrinfo(result); if (WSAGetLastError() != WSAEWOULDBLOCK) { log_socket_error(d, "connect"); closesocket(conn->sock); conn->sock = INVALID_SOCKET; return -1; } // Wait for connection. fd_set set; FD_ZERO(&set); FD_SET(conn->sock, &set); struct timeval time; time.tv_sec = 0; time.tv_usec = DEFAULT_TIMEOUT; res = select(0, &set, &set, &set, &time); if (res == SOCKET_ERROR) { log_socket_error(d, "select"); closesocket(conn->sock); conn->sock = INVALID_SOCKET; return -1; } else if (res == 0) { flogd(d, "Connection to %s timed out.\n", host); closesocket(conn->sock); conn->sock = INVALID_SOCKET; return -1; } // See if we have *actually* connected int error; int len = sizeof(error); if (getsockopt(conn->sock, SOL_SOCKET, SO_ERROR, (char *)&error, &len) == SOCKET_ERROR) { log_socket_error(d, "getsockopt"); closesocket(conn->sock); conn->sock = INVALID_SOCKET; return -1; } if (error) { WSASetLastError(error); log_socket_error(d, "connect"); closesocket(conn->sock); conn->sock = INVALID_SOCKET; return -1; } BOOL ndelay = 1; res = setsockopt(conn->sock, IPPROTO_TCP, TCP_NODELAY, (char *)&ndelay, sizeof(ndelay)); if (res == SOCKET_ERROR) { log_socket_error(d, "setsockopt"); closesocket(conn->sock); conn->sock = INVALID_SOCKET; return -1; } flogd(d, "Connected.\n"); // After we connect, the host will send an initial status response. dac_read_resp(d, DEFAULT_TIMEOUT); dac_dump_resp(d); char c = 'p'; dac_sendall(d, &c, 1); dac_read_resp(d, DEFAULT_TIMEOUT); dac_dump_resp(d); flogd(d, "Sent.\n"); return 0; }
void notify_thread(LIBEVENT_THREAD *thread) { if (send(thread->notify[1], "", 1, 0) != 1) { log_socket_error(EXTENSION_LOG_WARNING, NULL, "Failed to notify thread: %s"); } }