Mercurial > cabal
view sources/network.cpp @ 6:9be05a31b7f9
Enqlave IRC Network => Vaygr IRC Network
-Os optimizations by default
temporary functions' arguments rename
*char => NULL
bool => true|false
renamed some global vars, removed debug info
| author | Vlad Glagolev <enqlave@gmail.com> |
|---|---|
| date | Sun, 27 Jan 2008 17:23:14 +0300 |
| parents | 0faceb076254 |
| children | 8d54d9fdeca3 |
line wrap: on
line source
/** * network.cpp (2007-04-02) * * -- CABAL -- network essentials (sockets, etc.) * * Copyright (c) 2007-2008 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.hpp" // required: network.hpp Network::Network() { cout << "NETWORK: going online...\n"; } Network::~Network() { closeSocket(); cout << "NETWORK: offline\n"; } void Network::sendMsg(string m) { if (cs == -1) return; if (CABAL->debug) cout << "<- " << cs << " -- " << m << endl; send(cs, (m + "\n").c_str(), (m + "\n").size(), 0); } string Network::receiveMsg() { if (cs == -1) return 0; if (canRead(cs)) { 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) shut("remote server closed connection"); else if (err < 0) shut("failed to receive data"); else sbuffer += cbuffer; } } else if (!err) shut("remote server closed connection"); return sbuffer; } return ""; } bool Network::resolveHost(pchar name, struct address_type *a, int inet) { #ifdef ENABLE_IPV6 bool e = false; 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) { 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 = true; 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 = true; break; default: e = false; } } if (e) break; res = res->ai_next; } freeaddrinfo(reso); return e; #else // ! ENABLE_IPV6 if (inet && inet != AF_INET) return 0; a->inet = AF_INET; struct hostent *he; if (!(he = gethostbyname(name))) { a->sa.sin_addr.s_addr = inet_addr(name); if (a->sa.sin_addr.s_addr) 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::activateTCP(int port, pchar host) { cs = socket(address.inet, SOCK_STREAM, IPPROTO_TCP); if (cs == -1) return 0; if (host) { struct address_type a; if (!resolveHost(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 = false; connecting = true; cout << "NETWORK: socket opened..........: " << cs << endl; return 1; } bool Network::openHost() { 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 = true; connecting = false; return 1; } if (errno != EWOULDBLOCK && errno != EINPROGRESS && errno != EALREADY) { closeSocket(); connecting = false; return 0; } return 1; } connected = true; connecting = false; cout << "NETWORK: socket connected.......: " << cs << endl; return 1; } bool Network::closeSocket() { 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; }
