Mercurial > cabal
comparison 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 |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:bafff9de2a76 |
|---|---|
| 1 /** | |
| 2 * network.cpp (2007-04-02) | |
| 3 * | |
| 4 * -- CABAL -- network essentials (sockets, etc.) | |
| 5 * | |
| 6 * Copyright (c) 2007 Vlad Glagolev <enqlave@gmail.com> | |
| 7 * All rights reserved. | |
| 8 * | |
| 9 * Permission to use, copy, modify, and distribute this software for any | |
| 10 * purpose with or without fee is hereby granted, provided that the above | |
| 11 * copyright notice and this permission notice appear in all copies. | |
| 12 * | |
| 13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
| 14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
| 15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
| 16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
| 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
| 18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
| 19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
| 20 */ | |
| 21 | |
| 22 #include "cabal.h" // required: network.h | |
| 23 | |
| 24 Network::Network() | |
| 25 { | |
| 26 cout << "NETWORK: going online...\n"; | |
| 27 } | |
| 28 | |
| 29 Network::~Network() | |
| 30 { | |
| 31 socketClose(); | |
| 32 | |
| 33 cout << "NETWORK: offline\n"; | |
| 34 } | |
| 35 | |
| 36 void Network::msgSend (string data) | |
| 37 { | |
| 38 if (cs == -1) | |
| 39 return; | |
| 40 | |
| 41 if (CABAL->debug) | |
| 42 cout << "<- " << cs << " -- " << data << endl; | |
| 43 | |
| 44 send (cs, (data + "\n").c_str(), (data + "\n").size(), 0); | |
| 45 } | |
| 46 | |
| 47 string Network::msgReceive() | |
| 48 { | |
| 49 if (cs == -1) | |
| 50 return 0; | |
| 51 | |
| 52 if (canRead(cs) == 1) { | |
| 53 string sbuffer = ""; | |
| 54 char cbuffer; | |
| 55 | |
| 56 int err = recv (cs, &cbuffer, 1, 0); | |
| 57 | |
| 58 if (err > 0) { | |
| 59 sbuffer += cbuffer; | |
| 60 | |
| 61 while (1) { | |
| 62 if (sbuffer[sbuffer.size() - 1] == '\n') { | |
| 63 sbuffer = (sbuffer.substr (0, 1) == ":") | |
| 64 ? sbuffer.substr (1, sbuffer.size() - 3) | |
| 65 : sbuffer.substr (0, sbuffer.size() - 2); | |
| 66 | |
| 67 if (CABAL->debug) | |
| 68 cout << "-> " << cs << " -- " << sbuffer << endl; | |
| 69 | |
| 70 return sbuffer; | |
| 71 } | |
| 72 | |
| 73 err = recv (cs, &cbuffer, 1, 0); | |
| 74 | |
| 75 if (err == 0) | |
| 76 shut ("remote server closed connection"); | |
| 77 else if (err < 0) | |
| 78 shut ("failed to receive data"); | |
| 79 else | |
| 80 sbuffer += cbuffer; | |
| 81 } | |
| 82 } else if (err == 0) | |
| 83 shut ("remote server closed connection"); | |
| 84 | |
| 85 return sbuffer; | |
| 86 } | |
| 87 | |
| 88 return ""; | |
| 89 } | |
| 90 | |
| 91 bool Network::hostResolve(pchar name, struct address_type *a, int inet) | |
| 92 { | |
| 93 #ifdef ENABLE_IPV6 | |
| 94 | |
| 95 bool e = 0; | |
| 96 | |
| 97 struct addrinfo hints, *res, *reso; | |
| 98 struct sockaddr_in *in; | |
| 99 struct sockaddr_in6 *in6; | |
| 100 | |
| 101 memset(&hints, 0, sizeof (hints)); | |
| 102 | |
| 103 hints.ai_socktype = SOCK_STREAM; | |
| 104 | |
| 105 if (getaddrinfo(name, "domain", &hints, &res) < 0) | |
| 106 return 0; | |
| 107 | |
| 108 reso = res; | |
| 109 | |
| 110 while (res != 0) { | |
| 111 if (!inet || res->ai_family == inet) { | |
| 112 switch (res->ai_family) { | |
| 113 case AF_INET6: | |
| 114 a->inet = AF_INET6; | |
| 115 in6 = (struct sockaddr_in6 *)res->ai_addr; | |
| 116 memcpy (&a->sa6.sin6_addr, &in6->sin6_addr, \ | |
| 117 sizeof (struct in6_addr)); | |
| 118 e = 1; | |
| 119 break; | |
| 120 case AF_INET: | |
| 121 a->inet = AF_INET; | |
| 122 in = (struct sockaddr_in *)res->ai_addr; | |
| 123 memcpy (&a->sa.sin_addr, &in->sin_addr, \ | |
| 124 sizeof (struct in_addr)); | |
| 125 e = 1; | |
| 126 break; | |
| 127 default: | |
| 128 e = 0; | |
| 129 } | |
| 130 } | |
| 131 | |
| 132 if (e) | |
| 133 break; | |
| 134 | |
| 135 res = res->ai_next; | |
| 136 } | |
| 137 | |
| 138 freeaddrinfo (reso); | |
| 139 | |
| 140 return e; | |
| 141 | |
| 142 #else | |
| 143 | |
| 144 if (inet != 0 && inet != AF_INET) | |
| 145 return 0; | |
| 146 | |
| 147 a->inet = AF_INET; | |
| 148 | |
| 149 struct hostent *he; | |
| 150 | |
| 151 if ((he = gethostbyname (name)) == 0) { | |
| 152 a->sa.sin_addr.s_addr = inet_addr (name); | |
| 153 | |
| 154 if (a->sa.sin_addr.s_addr == 1) | |
| 155 return 0; | |
| 156 } else | |
| 157 memcpy (&a->sa.sin_addr.s_addr, he->h_addr_list[0], he->h_length); | |
| 158 | |
| 159 return 1; | |
| 160 | |
| 161 #endif // ENABLE_IPV6 | |
| 162 } | |
| 163 | |
| 164 bool Network::tcpActivate (int port, pchar host) | |
| 165 { | |
| 166 cs = socket (address.inet, SOCK_STREAM, IPPROTO_TCP); | |
| 167 | |
| 168 if (cs == -1) | |
| 169 return 0; | |
| 170 | |
| 171 if (host != 0) { | |
| 172 struct address_type a; | |
| 173 | |
| 174 if (!hostResolve (host, &a, address.inet)) { | |
| 175 close (cs); | |
| 176 return 0; | |
| 177 } | |
| 178 | |
| 179 int e; | |
| 180 | |
| 181 #ifdef ENABLE_IPV6 | |
| 182 if (a.inet == AF_INET6) | |
| 183 e = bind (cs, (struct sockaddr *)&a.sa6, sizeof (a.sa6)); | |
| 184 else | |
| 185 #endif // ENABLE_IPV6 | |
| 186 e = bind (cs, (struct sockaddr *)&a.sa, sizeof (a.sa)); | |
| 187 | |
| 188 if (e == -1) { | |
| 189 close (cs); | |
| 190 return 0; | |
| 191 } | |
| 192 } | |
| 193 | |
| 194 #ifdef ENABLE_IPV6 | |
| 195 if (address.inet == AF_INET6) { | |
| 196 address.sa6.sin6_family = AF_INET6; | |
| 197 address.sa6.sin6_port = htons (port); | |
| 198 } | |
| 199 else { | |
| 200 #endif // ENABLE_IPV6 | |
| 201 address.sa.sin_family = AF_INET; | |
| 202 address.sa.sin_port = htons (port); | |
| 203 #ifdef ENABLE_IPV6 | |
| 204 } | |
| 205 #endif // ENABLE_IPV6 | |
| 206 | |
| 207 socklen_t parm; | |
| 208 | |
| 209 setsockopt (cs, IPPROTO_TCP, TCP_NODELAY, (pchar)&parm, sizeof (parm)); | |
| 210 | |
| 211 connected = 0; | |
| 212 connecting = 1; | |
| 213 | |
| 214 cout << "NETWORK: socket opened........... " << cs << endl; | |
| 215 | |
| 216 return 1; | |
| 217 } | |
| 218 | |
| 219 bool Network::hostOpen() | |
| 220 { | |
| 221 int e; | |
| 222 | |
| 223 #ifdef ENABLE_IPV6 | |
| 224 if (address.inet == AF_INET6) | |
| 225 e = connect (cs, (struct sockaddr *)&address.sa6, sizeof (address.sa6)); | |
| 226 else | |
| 227 #endif // ENABLE_IPV6 | |
| 228 e = connect (cs, (struct sockaddr *)&address.sa, sizeof (address.sa)); | |
| 229 | |
| 230 if (e == -1) { | |
| 231 if (errno == EISCONN) { | |
| 232 connected = 1; | |
| 233 connecting = 0; | |
| 234 | |
| 235 return 1; | |
| 236 } | |
| 237 | |
| 238 if (errno != EWOULDBLOCK && errno != EINPROGRESS && errno != EALREADY) { | |
| 239 socketClose(); | |
| 240 | |
| 241 connecting = 0; | |
| 242 | |
| 243 return 0; | |
| 244 } | |
| 245 | |
| 246 return 1; | |
| 247 } | |
| 248 | |
| 249 connected = 1; | |
| 250 connecting = 0; | |
| 251 | |
| 252 cout << "NETWORK: socket connected........ " << cs << endl; | |
| 253 | |
| 254 return 1; | |
| 255 } | |
| 256 | |
| 257 bool Network::socketClose() | |
| 258 { | |
| 259 if (cs == -1) | |
| 260 return 0; | |
| 261 | |
| 262 close (cs); | |
| 263 | |
| 264 cs = -1; | |
| 265 | |
| 266 return 1; | |
| 267 } | |
| 268 | |
| 269 int Network::canRead (int socket) | |
| 270 { | |
| 271 FD_ZERO (&rs); | |
| 272 FD_SET (socket, &rs); | |
| 273 | |
| 274 timeout.tv_sec = 0; | |
| 275 timeout.tv_usec = 1; | |
| 276 | |
| 277 int e = select (socket + 1, &rs, 0, 0, &timeout); | |
| 278 | |
| 279 FD_ZERO (&rs); | |
| 280 | |
| 281 return e; | |
| 282 } | |
| 283 | |
| 284 int Network::canWrite (int socket) | |
| 285 { | |
| 286 FD_ZERO (&ws); | |
| 287 FD_SET (socket, &ws); | |
| 288 | |
| 289 timeout.tv_sec = 0; | |
| 290 timeout.tv_usec = 1; | |
| 291 | |
| 292 int e = select (socket + 1, 0, &ws, 0, &timeout); | |
| 293 | |
| 294 FD_ZERO (&ws); | |
| 295 | |
| 296 return e; | |
| 297 } |
