#include "orkestra_tcp_win.hpp" #include #include namespace fiko { namespace { bool wsaBaslat() { WSADATA wd; return WSAStartup(MAKEWORD(2, 2), &wd) == 0; } void nonBlocking(SOCKET s) { u_long nb = 1; ::ioctlsocket(s, FIONBIO, &nb); } } // namespace // ── TcpBaglantiWin ─────────────────────────────────────────────────────────── TcpBaglantiWin::TcpBaglantiWin(uintptr_t kabulSoket) { if (!kabulSoket) return; if (!wsaBaslat()) return; // kabul eden zaten başlattı — ref sayacı dengeli kalsın wsa_ = true; soket_ = kabulSoket; nonBlocking((SOCKET)soket_); acik_ = true; } bool TcpBaglantiWin::baglan(const char* ip, uint16_t port) { kapat(); if (!wsaBaslat()) return false; wsa_ = true; SOCKET s = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (s == INVALID_SOCKET) { kapat(); return false; } sockaddr_in adres{}; adres.sin_family = AF_INET; adres.sin_port = htons(port); if (::inet_pton(AF_INET, ip, &adres.sin_addr) != 1 || ::connect(s, (sockaddr*)&adres, sizeof(adres)) != 0) { ::closesocket(s); kapat(); return false; } nonBlocking(s); // bağlandıktan sonra al/gonder kareyi bloklamaz soket_ = (uintptr_t)s; acik_ = true; return true; } void TcpBaglantiWin::kapat() { if (acik_) ::closesocket((SOCKET)soket_); if (wsa_) ::WSACleanup(); soket_ = 0; acik_ = false; wsa_ = false; } bool TcpBaglantiWin::gonder(const std::string& veri) { if (!acik_) return false; size_t yazilan = 0; int denemeler = 0; while (yazilan < veri.size()) { const int n = ::send((SOCKET)soket_, veri.data() + yazilan, (int)(veri.size() - yazilan), 0); if (n > 0) { yazilan += (size_t)n; continue; } if (n == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK && ++denemeler < 100) { Sleep(1); // tampon dolu — kısa bekle (çerçeveler küçük; 100 ms üst sınır) continue; } return false; } return true; } int TcpBaglantiWin::al(std::string& veri) { if (!acik_) return -1; char tampon[4096]; const int n = ::recv((SOCKET)soket_, tampon, (int)sizeof(tampon), 0); if (n > 0) { veri.assign(tampon, (size_t)n); return n; } if (n == 0) return -1; // karşı taraf kapattı return WSAGetLastError() == WSAEWOULDBLOCK ? 0 : -1; } // ── TcpDinleyiciWin ────────────────────────────────────────────────────────── bool TcpDinleyiciWin::ac(uint16_t port) { kapat(); if (!wsaBaslat()) return false; wsa_ = true; SOCKET s = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (s == INVALID_SOCKET) { kapat(); return false; } sockaddr_in adres{}; adres.sin_family = AF_INET; adres.sin_addr.s_addr = INADDR_ANY; adres.sin_port = htons(port); if (::bind(s, (sockaddr*)&adres, sizeof(adres)) != 0 || ::listen(s, 8) != 0) { ::closesocket(s); // port meşgul → başka fikocad dinliyor (gömülü ajan o) kapat(); return false; } nonBlocking(s); soket_ = (uintptr_t)s; port_ = port; acik_ = true; return true; } void TcpDinleyiciWin::kapat() { if (acik_) ::closesocket((SOCKET)soket_); if (wsa_) ::WSACleanup(); soket_ = 0; port_ = 0; acik_ = false; wsa_ = false; } uintptr_t TcpDinleyiciWin::kabulEt() { if (!acik_) return 0; const SOCKET s = ::accept((SOCKET)soket_, nullptr, nullptr); return s == INVALID_SOCKET ? 0 : (uintptr_t)s; } } // namespace fiko