Mercurial > cabal
view sources/network.cpp @ 0:bafff9de2a76
Initial commit since summer'07
| author | Vlad Glagolev <enqlave@gmail.com> |
|---|---|
| date | Sun, 20 Jan 2008 19:25:25 +0300 |
| parents | |
| children | 19227b0b7cc1 |
line wrap: on
line source
/** * network.cpp (2007-04-02) * * -- CABAL -- network essentials (sockets, etc.) * * Copyright (c) 2007 Vlad Glagolev <enqlave@gmail.com> * All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "cabal.h" // required: network.h Network::Network() { cout << "NETWORK: going online...\n"; } Network::~Network() { socketClose(); cout << "NETWORK: offline\n"; } void Network::msgSend (string data) { if (cs == -1) return; if (CABAL->debug) cout << "<- " << cs << " -- " << data << endl; send (cs, (data + "\n").c_str(), (data + "\n").size(), 0); } string Network::msgReceive() { if (cs == -1) return 0; if (canRead(cs) == 1) { string sbuffer = ""; char cbuffer; int err = recv (cs, &cbuffer, 1, 0); if (err > 0) { sbuffer += cbuffer; while (1) { if (sbuffer[sbuffer.size() - 1] == '\n') { sbuffer = (sbuffer.substr (0, 1) == ":") ? sbuffer.substr (1, sbuffer.size() - 3) : sbuffer.substr (0, sbuffer.size() - 2); if (CABAL->debug) cout << "-> " << cs << " -- " << sbuffer << endl; return sbuffer; } err = recv (cs, &cbuffer, 1, 0); if (err == 0) shut ("remote server closed connection"); else if (err < 0) shut ("failed to receive data"); else sbuffer += cbuffer; } } else if (err == 0) shut ("remote server closed connection"); return sbuffer; } return ""; } bool Network::hostResolve(pchar name, struct address_type *a, int inet) { #ifdef ENABLE_IPV6 bool e = 0; struct addrinfo hints, *res, *reso; struct sockaddr_in *in; struct sockaddr_in6 *in6; memset(&hints, 0, sizeof (hints)); hints.ai_socktype = SOCK_STREAM; if (getaddrinfo(name, "domain", &hints, &res) < 0) return 0; reso = res; while (res != 0) { if (!inet || res->ai_family == inet) { switch (res->ai_family) { case AF_INET6: a->inet = AF_INET6; in6 = (struct sockaddr_in6 *)res->ai_addr; memcpy (&a->sa6.sin6_addr, &in6->sin6_addr, \ sizeof (struct in6_addr)); e = 1; break; case AF_INET: a->inet = AF_INET; in = (struct sockaddr_in *)res->ai_addr; memcpy (&a->sa.sin_addr, &in->sin_addr, \ sizeof (struct in_addr)); e = 1; break; default: e = 0; } } if (e) break; res = res->ai_next; } freeaddrinfo (reso); return e; #else if (inet != 0 && inet != AF_INET) return 0; a->inet = AF_INET; struct hostent *he; if ((he = gethostbyname (name)) == 0) { a->sa.sin_addr.s_addr = inet_addr (name); if (a->sa.sin_addr.s_addr == 1) return 0; } else memcpy (&a->sa.sin_addr.s_addr, he->h_addr_list[0], he->h_length); return 1; #endif // ENABLE_IPV6 } bool Network::tcpActivate (int port, pchar host) { cs = socket (address.inet, SOCK_STREAM, IPPROTO_TCP); if (cs == -1) return 0; if (host != 0) { struct address_type a; if (!hostResolve (host, &a, address.inet)) { close (cs); return 0; } int e; #ifdef ENABLE_IPV6 if (a.inet == AF_INET6) e = bind (cs, (struct sockaddr *)&a.sa6, sizeof (a.sa6)); else #endif // ENABLE_IPV6 e = bind (cs, (struct sockaddr *)&a.sa, sizeof (a.sa)); if (e == -1) { close (cs); return 0; } } #ifdef ENABLE_IPV6 if (address.inet == AF_INET6) { address.sa6.sin6_family = AF_INET6; address.sa6.sin6_port = htons (port); } else { #endif // ENABLE_IPV6 address.sa.sin_family = AF_INET; address.sa.sin_port = htons (port); #ifdef ENABLE_IPV6 } #endif // ENABLE_IPV6 socklen_t parm; setsockopt (cs, IPPROTO_TCP, TCP_NODELAY, (pchar)&parm, sizeof (parm)); connected = 0; connecting = 1; cout << "NETWORK: socket opened........... " << cs << endl; return 1; } bool Network::hostOpen() { int e; #ifdef ENABLE_IPV6 if (address.inet == AF_INET6) e = connect (cs, (struct sockaddr *)&address.sa6, sizeof (address.sa6)); else #endif // ENABLE_IPV6 e = connect (cs, (struct sockaddr *)&address.sa, sizeof (address.sa)); if (e == -1) { if (errno == EISCONN) { connected = 1; connecting = 0; return 1; } if (errno != EWOULDBLOCK && errno != EINPROGRESS && errno != EALREADY) { socketClose(); connecting = 0; return 0; } return 1; } connected = 1; connecting = 0; cout << "NETWORK: socket connected........ " << cs << endl; return 1; } bool Network::socketClose() { if (cs == -1) return 0; close (cs); cs = -1; return 1; } int Network::canRead (int socket) { FD_ZERO (&rs); FD_SET (socket, &rs); timeout.tv_sec = 0; timeout.tv_usec = 1; int e = select (socket + 1, &rs, 0, 0, &timeout); FD_ZERO (&rs); return e; } int Network::canWrite (int socket) { FD_ZERO (&ws); FD_SET (socket, &ws); timeout.tv_sec = 0; timeout.tv_usec = 1; int e = select (socket + 1, 0, &ws, 0, &timeout); FD_ZERO (&ws); return e; }
