00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "global.hpp"
00019
00020 #include "serialization/binary_wml.hpp"
00021 #include "config.hpp"
00022 #include "gettext.hpp"
00023 #include "log.hpp"
00024 #include "network.hpp"
00025 #include "network_worker.hpp"
00026 #include "thread.hpp"
00027
00028 #include "SDL_net.h"
00029
00030 #include <algorithm>
00031 #include <cassert>
00032 #include <cerrno>
00033 #include <queue>
00034 #include <iostream>
00035 #include <set>
00036 #include <vector>
00037 #include <ctime>
00038
00039 #include <signal.h>
00040 #include <string.h>
00041 #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
00042 #undef INADDR_ANY
00043 #undef INADDR_BROADCAST
00044 #undef INADDR_NONE
00045 #include <windows.h>
00046 #else
00047 #include <sys/types.h>
00048 #include <sys/socket.h>
00049 #include <netinet/in.h>
00050 #include <netinet/tcp.h>
00051 #ifdef __BEOS__
00052 #include <socket.h>
00053 #else
00054 #include <fcntl.h>
00055 #endif
00056 #define SOCKET int
00057 #endif
00058
00059 #define DBG_NW LOG_STREAM(debug, network)
00060 #define LOG_NW LOG_STREAM(info, network)
00061 #define WRN_NW LOG_STREAM(warn, network)
00062 #define ERR_NW LOG_STREAM(err, network)
00063
00064
00065 namespace {
00066
00067
00068
00069
00070 struct connection_details {
00071 connection_details(TCPsocket sock, const std::string& host, int port)
00072 : sock(sock), host(host), port(port), remote_handle(0),
00073 connected_at(SDL_GetTicks())
00074 {}
00075
00076 TCPsocket sock;
00077 std::string host;
00078 int port;
00079
00080
00081
00082 int remote_handle;
00083
00084 int connected_at;
00085 };
00086
00087 typedef std::map<network::connection,connection_details> connection_map;
00088 connection_map connections;
00089
00090 network::connection connection_id = 1;
00091
00092
00093 time_t last_ping, last_ping_check = 0;
00094
00095 }
00096
00097 static int create_connection(TCPsocket sock, const std::string& host, int port)
00098 {
00099 connections.insert(std::pair<network::connection,connection_details>(connection_id,connection_details(sock,host,port)));
00100 return connection_id++;
00101 }
00102
00103 static connection_details& get_connection_details(network::connection handle)
00104 {
00105 const connection_map::iterator i = connections.find(handle);
00106 if(i == connections.end()) {
00107 throw network::error(_("invalid network handle"));
00108 }
00109
00110 return i->second;
00111 }
00112
00113 static TCPsocket get_socket(network::connection handle)
00114 {
00115 return get_connection_details(handle).sock;
00116 }
00117
00118 static void remove_connection(network::connection handle)
00119 {
00120 connections.erase(handle);
00121 }
00122
00123 static bool is_pending_remote_handle(network::connection handle)
00124 {
00125 const connection_details& details = get_connection_details(handle);
00126 return details.host != "" && details.remote_handle == 0;
00127 }
00128
00129 static void set_remote_handle(network::connection handle, int remote_handle)
00130 {
00131 get_connection_details(handle).remote_handle = remote_handle;
00132 }
00133
00134 static void check_error()
00135 {
00136 const TCPsocket sock = network_worker_pool::detect_error();
00137 if(sock) {
00138 for(connection_map::const_iterator i = connections.begin(); i != connections.end(); ++i) {
00139 if(i->second.sock == sock) {
00140 throw network::error(_("Client disconnected"),i->first);
00141 }
00142 }
00143 }
00144 }
00145
00146
00147
00148
00149
00150 static void check_timeout()
00151 {
00152 if (network::nconnections() == 0) {
00153 LOG_NW << "No network connections but last_ping is: " << last_ping;
00154 last_ping = 0;
00155 return;
00156 }
00157 const time_t& now = time(NULL);
00158 DBG_NW << "Last ping: '" << last_ping << "' Current time: '" << now
00159 << "' Time since last ping: " << now - last_ping << "s\n";
00160
00161 if (last_ping_check + 10 <= now) last_ping = now;
00162 if (static_cast<time_t>(last_ping + network::ping_timeout) <= now) {
00163
00164 int timeout = now - last_ping;
00165 ERR_NW << "No server ping since " << timeout
00166 << " seconds. Connection timed out.\n";
00167 utils::string_map symbols;
00168 symbols["timeout"] = lexical_cast<std::string>(timeout);
00169 throw network::error(vngettext("No server ping since $timeout second. "
00170 "Connection timed out.", "No server ping since $timeout seconds. "
00171 "Connection timed out.", timeout, symbols));
00172 }
00173 last_ping_check = now;
00174 }
00175
00176
00177 namespace {
00178
00179 SDLNet_SocketSet socket_set = 0;
00180 std::set<network::connection> waiting_sockets;
00181 typedef std::vector<network::connection> sockets_list;
00182 sockets_list sockets;
00183
00184
00185 struct partial_buffer {
00186 partial_buffer() : upto(0) {}
00187 std::vector<char> buf;
00188 size_t upto;
00189 };
00190
00191 TCPsocket server_socket;
00192
00193 std::deque<network::connection> disconnection_queue;
00194 std::set<network::connection> bad_sockets;
00195
00196 network_worker_pool::manager* worker_pool_man = NULL;
00197
00198 }
00199
00200 namespace network {
00201
00202
00203
00204
00205 unsigned int ping_timeout = 0;
00206
00207 connection_stats::connection_stats(int sent, int received, int connected_at)
00208 : bytes_sent(sent), bytes_received(received), time_connected(SDL_GetTicks() - connected_at)
00209 {}
00210
00211 connection_stats get_connection_stats(connection connection_num)
00212 {
00213 connection_details& details = get_connection_details(connection_num);
00214 return connection_stats(get_send_stats(connection_num).total,get_receive_stats(connection_num).total,details.connected_at);
00215 }
00216
00217 error::error(const std::string& msg, connection sock) : message(msg), socket(sock)
00218 {
00219 if(socket) {
00220 bad_sockets.insert(socket);
00221 }
00222 }
00223
00224 void error::disconnect()
00225 {
00226 if(socket) network::disconnect(socket);
00227 }
00228
00229 pending_statistics get_pending_stats()
00230 {
00231 return network_worker_pool::get_pending_stats();
00232 }
00233
00234 manager::manager(size_t min_threads, size_t max_threads) : free_(true)
00235 {
00236
00237 if(socket_set) {
00238 free_ = false;
00239 return;
00240 }
00241
00242
00243 #if !(defined(_WIN32) || defined(__APPLE__) || defined(__AMIGAOS4__))
00244 WRN_NW << "ignoring SIGPIPE\n";
00245 signal(SIGPIPE,SIG_IGN);
00246 #endif
00247
00248 if(SDLNet_Init() == -1) {
00249 ERR_NW << "could not initialize SDLNet; throwing error...\n";
00250 throw error(SDL_GetError());
00251 }
00252
00253 socket_set = SDLNet_AllocSocketSet(512);
00254
00255 worker_pool_man = new network_worker_pool::manager(min_threads, max_threads);
00256 }
00257
00258 manager::~manager()
00259 {
00260 if(free_) {
00261 disconnect();
00262 delete worker_pool_man;
00263 worker_pool_man = NULL;
00264 SDLNet_FreeSocketSet(socket_set);
00265 socket_set = 0;
00266 waiting_sockets.clear();
00267 SDLNet_Quit();
00268 }
00269 }
00270
00271 void set_raw_data_only()
00272 {
00273 network_worker_pool::set_raw_data_only();
00274 }
00275
00276 server_manager::server_manager(int port, CREATE_SERVER create_server) : free_(false)
00277 {
00278 if(create_server != NO_SERVER && !server_socket) {
00279 try {
00280 server_socket = get_socket(connect("",port));
00281 } catch(network::error& e) {
00282 if(create_server == MUST_CREATE_SERVER) {
00283 throw e;
00284 } else {
00285 return;
00286 }
00287 }
00288
00289 DBG_NW << "server socket initialized: " << server_socket << "\n";
00290 free_ = true;
00291 }
00292 }
00293
00294 server_manager::~server_manager()
00295 {
00296 stop();
00297 }
00298
00299 void server_manager::stop()
00300 {
00301 if(free_) {
00302 SDLNet_TCP_Close(server_socket);
00303 server_socket = 0;
00304 free_ = false;
00305 }
00306 }
00307
00308 bool server_manager::is_running() const
00309 {
00310 return server_socket != NULL;
00311 }
00312
00313 size_t nconnections()
00314 {
00315 return sockets.size();
00316 }
00317
00318 bool is_server()
00319 {
00320 return server_socket != 0;
00321 }
00322
00323 namespace {
00324
00325 class connect_operation : public threading::async_operation
00326 {
00327 public:
00328 connect_operation(const std::string& host, int port) : host_(host), port_(port), error_(NULL), connect_(0)
00329 {}
00330
00331 void check_error();
00332 void run();
00333
00334 network::connection result() const { return connect_; }
00335
00336 private:
00337 std::string host_;
00338 int port_;
00339 const char* error_;
00340 network::connection connect_;
00341 };
00342
00343 void connect_operation::check_error()
00344 {
00345 if(error_ != NULL) {
00346 throw error(error_);
00347 }
00348 }
00349
00350 namespace {
00351 struct _TCPsocket {
00352 int ready;
00353 SOCKET channel;
00354 IPaddress remoteAddress;
00355 IPaddress localAddress;
00356 int sflag;
00357 };
00358 }
00359
00360 void connect_operation::run()
00361 {
00362 char* const hostname = host_.empty() ? NULL : const_cast<char*>(host_.c_str());
00363 IPaddress ip;
00364 if(SDLNet_ResolveHost(&ip,hostname,port_) == -1) {
00365 error_ = "Could not connect to host";
00366 return;
00367 }
00368
00369 TCPsocket sock = SDLNet_TCP_Open(&ip);
00370 if(!sock) {
00371 error_ = hostname == NULL ? "Could not bind to port" :
00372 "Could not connect to host";
00373 return;
00374 }
00375
00376 #ifdef TCP_NODELAY
00377
00378
00379 {
00380 _TCPsocket* raw_sock = reinterpret_cast<_TCPsocket*>(sock);
00381 int no = 0;
00382 setsockopt(raw_sock->channel, IPPROTO_TCP, TCP_NODELAY, (char*)&no, sizeof(no));
00383 }
00384 #endif
00385
00386
00387 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
00388 {
00389 unsigned long mode = 1;
00390 ioctlsocket (((_TCPsocket*)sock)->channel, FIONBIO, &mode);
00391 }
00392 #elif !defined(__BEOS__)
00393 int flags;
00394 flags = fcntl((reinterpret_cast<_TCPsocket*>(sock))->channel, F_GETFL, 0);
00395 #if defined(O_NONBLOCK)
00396 flags |= O_NONBLOCK;
00397 #elif defined(O_NDELAY)
00398 flags |= O_NDELAY;
00399 #elif defined(FNDELAY)
00400 flags |= FNDELAY;
00401 #endif
00402 if(fcntl((reinterpret_cast<_TCPsocket*>(sock))->channel, F_SETFL, flags) == -1) {
00403 error_ = ("Could not make socket non-blocking: " + std::string(strerror(errno))).c_str();
00404 return;
00405 }
00406 #else
00407 int on = 1;
00408 if(setsockopt(((_TCPsocket*)sock)->channel, SOL_SOCKET, SO_NONBLOCK, &on, sizeof(int)) < 0) {
00409 error_ = ("Could not make socket non-blocking: " + std::string(strerror(errno))).c_str();
00410 return;
00411 }
00412 #endif
00413
00414
00415 if(hostname == NULL) {
00416 const threading::lock l(get_mutex());
00417 connect_ = create_connection(sock,"",port_);
00418 return;
00419 }
00420
00421
00422 char buf[4];
00423 SDLNet_Write32(0,buf);
00424 const int nbytes = SDLNet_TCP_Send(sock,buf,4);
00425 if(nbytes != 4) {
00426 SDLNet_TCP_Close(sock);
00427 error_ = "Could not send initial handshake";
00428 return;
00429 }
00430
00431
00432 const threading::lock l(get_mutex());
00433 DBG_NW << "sent handshake...\n";
00434
00435 if(is_aborted()) {
00436 DBG_NW << "connect operation aborted by calling thread\n";
00437 SDLNet_TCP_Close(sock);
00438 return;
00439 }
00440
00441
00442 connect_ = create_connection(sock,host_,port_);
00443
00444 const int res = SDLNet_TCP_AddSocket(socket_set,sock);
00445 if(res == -1) {
00446 SDLNet_TCP_Close(sock);
00447 error_ = "Could not add socket to socket set";
00448 return;
00449 }
00450
00451 waiting_sockets.insert(connect_);
00452
00453 sockets.push_back(connect_);
00454
00455 while(!notify_finished()) {};
00456 }
00457
00458
00459 }
00460
00461
00462 connection connect(const std::string& host, int port)
00463 {
00464 connect_operation op(host,port);
00465 op.run();
00466 op.check_error();
00467 return op.result();
00468 }
00469
00470 connection connect(const std::string& host, int port, threading::waiter& waiter)
00471 {
00472 const threading::async_operation_holder<connect_operation> op(new connect_operation(host,port));
00473 const connect_operation::RESULT res = op.operation().execute(waiter);
00474 if(res == connect_operation::ABORTED) {
00475 return 0;
00476 }
00477
00478 op.operation().check_error();
00479 return op.operation().result();
00480 }
00481
00482 connection accept_connection()
00483 {
00484 if(!server_socket) {
00485 return 0;
00486 }
00487
00488
00489
00490
00491
00492
00493
00494 static std::vector<TCPsocket> pending_sockets;
00495 static SDLNet_SocketSet pending_socket_set = 0;
00496
00497 const TCPsocket sock = SDLNet_TCP_Accept(server_socket);
00498 if(sock) {
00499 DBG_NW << "received connection. Pending handshake...\n";
00500 pending_sockets.push_back(sock);
00501 if(pending_socket_set == 0) {
00502 pending_socket_set = SDLNet_AllocSocketSet(512);
00503 }
00504
00505 if(pending_socket_set != 0) {
00506 SDLNet_TCP_AddSocket(pending_socket_set,sock);
00507 }
00508 }
00509
00510 if(pending_socket_set == 0) {
00511 return 0;
00512 }
00513
00514 const int set_res = SDLNet_CheckSockets(pending_socket_set,0);
00515 if(set_res <= 0) {
00516 return 0;
00517 }
00518
00519 DBG_NW << "pending socket activity...\n";
00520
00521 for(std::vector<TCPsocket>::iterator i = pending_sockets.begin(); i != pending_sockets.end(); ++i) {
00522 if(!SDLNet_SocketReady(*i)) {
00523 continue;
00524 }
00525
00526
00527
00528 char buf[4];
00529
00530 const TCPsocket sock = *i;
00531 SDLNet_TCP_DelSocket(pending_socket_set,sock);
00532 pending_sockets.erase(i);
00533
00534 DBG_NW << "receiving data from pending socket...\n";
00535
00536 const int len = SDLNet_TCP_Recv(sock,buf,4);
00537 if(len != 4) {
00538 WRN_NW << "pending socket disconnected\n";
00539 SDLNet_TCP_Close(sock);
00540 return 0;
00541 }
00542
00543 const int handle = SDLNet_Read32(buf);
00544
00545 DBG_NW << "received handshake from client: '" << handle << "'\n";
00546
00547 const int res = SDLNet_TCP_AddSocket(socket_set,sock);
00548 if(res == -1) {
00549 SDLNet_TCP_Close(sock);
00550
00551 throw network::error(_("Could not add socket to socket set"));
00552 }
00553
00554
00555 const connection connect = create_connection(sock,"",0);
00556
00557
00558 SDLNet_Write32(connect,buf);
00559 const int nbytes = SDLNet_TCP_Send(sock,buf,4);
00560 if(nbytes != 4) {
00561 SDLNet_TCP_DelSocket(socket_set,sock);
00562 SDLNet_TCP_Close(sock);
00563 remove_connection(connect);
00564 throw network::error(_("Could not send initial handshake"));
00565 }
00566
00567 waiting_sockets.insert(connect);
00568 sockets.push_back(connect);
00569 return connect;
00570 }
00571
00572 return 0;
00573 }
00574
00575 bool disconnect(connection s, bool force)
00576 {
00577 if(s == 0) {
00578 while(sockets.empty() == false) {
00579 assert(sockets.back() != 0);
00580
00581 while(disconnect(sockets.back()) == false) {
00582 SDL_Delay(1);
00583 }
00584 }
00585 return true;
00586 }
00587 if (!is_server()) last_ping = 0;
00588
00589 const connection_map::iterator info = connections.find(s);
00590 if(info != connections.end()) {
00591 if (!network_worker_pool::close_socket(info->second.sock, force)) {
00592 return false;
00593 }
00594 }
00595
00596 bad_sockets.erase(s);
00597
00598 std::deque<network::connection>::iterator dqi = std::find(disconnection_queue.begin(),disconnection_queue.end(),s);
00599 if(dqi != disconnection_queue.end()) {
00600 disconnection_queue.erase(dqi);
00601 }
00602
00603 const sockets_list::iterator i = std::find(sockets.begin(),sockets.end(),s);
00604 if(i != sockets.end()) {
00605 sockets.erase(i);
00606
00607 const TCPsocket sock = get_socket(s);
00608
00609 waiting_sockets.erase(s);
00610 SDLNet_TCP_DelSocket(socket_set,sock);
00611 SDLNet_TCP_Close(sock);
00612
00613 remove_connection(s);
00614 } else {
00615 if(sockets.size() == 1) {
00616 DBG_NW << "valid socket: " << static_cast<int>(*sockets.begin()) << "\n";
00617 }
00618 }
00619
00620 return true;
00621 }
00622
00623 void queue_disconnect(network::connection sock)
00624 {
00625 disconnection_queue.push_back(sock);
00626 }
00627
00628 connection receive_data(config& cfg, connection connection_num, unsigned int timeout)
00629 {
00630 unsigned int start_ticks = SDL_GetTicks();
00631 while(true) {
00632 const connection res = receive_data(cfg,connection_num);
00633 if(res != 0) {
00634 return res;
00635 }
00636
00637 if(timeout > SDL_GetTicks() - start_ticks) {
00638 SDL_Delay(1);
00639 }
00640 else
00641 {
00642 break;
00643 }
00644
00645 }
00646
00647 return 0;
00648 }
00649
00650 connection receive_data(config& cfg, connection connection_num)
00651 {
00652 if(!socket_set) {
00653 return 0;
00654 }
00655
00656 check_error();
00657
00658 if(disconnection_queue.empty() == false) {
00659 const network::connection sock = disconnection_queue.front();
00660 disconnection_queue.pop_front();
00661 throw error("",sock);
00662 }
00663
00664 if(bad_sockets.count(connection_num) || bad_sockets.count(0)) {
00665 return 0;
00666 }
00667
00668 if(sockets.empty()) {
00669 return 0;
00670 }
00671
00672 const int res = SDLNet_CheckSockets(socket_set,0);
00673
00674 for(std::set<network::connection>::iterator i = waiting_sockets.begin(); res != 0 && i != waiting_sockets.end(); ) {
00675 connection_details& details = get_connection_details(*i);
00676 const TCPsocket sock = details.sock;
00677 if(SDLNet_SocketReady(sock)) {
00678
00679
00680
00681 if(is_pending_remote_handle(*i)) {
00682 char buf[4];
00683 int len = SDLNet_TCP_Recv(sock,buf,4);
00684 if(len != 4) {
00685 throw error("Remote host disconnected",*i);
00686 }
00687
00688 const int remote_handle = SDLNet_Read32(buf);
00689 set_remote_handle(*i,remote_handle);
00690
00691 continue;
00692 }
00693
00694 waiting_sockets.erase(i++);
00695 SDLNet_TCP_DelSocket(socket_set,sock);
00696 network_worker_pool::receive_data(sock);
00697 } else {
00698 ++i;
00699 }
00700 }
00701
00702
00703 TCPsocket sock = connection_num == 0 ? 0 : get_socket(connection_num);
00704 TCPsocket s = sock;
00705 sock = network_worker_pool::get_received_data(sock,cfg);
00706 if (sock == NULL) {
00707 if (!is_server() && last_ping != 0 && ping_timeout != 0)
00708 {
00709 if (connection_num == 0)
00710 {
00711 s = get_socket(sockets.back());
00712 }
00713 if (!network_worker_pool::is_locked(s))
00714 {
00715 check_timeout();
00716 }
00717 }
00718 return 0;
00719 }
00720
00721 SDLNet_TCP_AddSocket(socket_set,sock);
00722
00723 connection result = 0;
00724 for(connection_map::const_iterator j = connections.begin(); j != connections.end(); ++j) {
00725 if(j->second.sock == sock) {
00726 result = j->first;
00727 break;
00728 }
00729 }
00730 if(!cfg.empty()) {
00731 DBG_NW << "RECEIVED from: " << result << ": " << cfg;
00732 }
00733
00734 assert(result != 0);
00735 waiting_sockets.insert(result);
00736 if(!is_server()) {
00737 const time_t& now = time(NULL);
00738 const string_map::const_iterator ping = cfg.values.find("ping");
00739 if (ping != cfg.values.end()) {
00740 LOG_NW << "Lag: " << (now - lexical_cast<time_t>(cfg["ping"])) << "\n";
00741 last_ping = now;
00742 } else if (last_ping != 0) {
00743 last_ping = now;
00744 }
00745 }
00746 return result;
00747 }
00748
00749 connection receive_data(std::vector<char>& buf)
00750 {
00751 if(!socket_set) {
00752 return 0;
00753 }
00754
00755 check_error();
00756
00757 if(disconnection_queue.empty() == false) {
00758 const network::connection sock = disconnection_queue.front();
00759 disconnection_queue.pop_front();
00760 throw error("",sock);
00761 }
00762
00763 if(bad_sockets.count(0)) {
00764 return 0;
00765 }
00766
00767 if(sockets.empty()) {
00768 return 0;
00769 }
00770
00771 const int res = SDLNet_CheckSockets(socket_set,0);
00772
00773 for(std::set<network::connection>::iterator i = waiting_sockets.begin(); res != 0 && i != waiting_sockets.end(); ) {
00774 connection_details& details = get_connection_details(*i);
00775 const TCPsocket sock = details.sock;
00776 if(SDLNet_SocketReady(sock)) {
00777
00778
00779
00780 if(is_pending_remote_handle(*i)) {
00781 char buf[4];
00782 int len = SDLNet_TCP_Recv(sock,buf,4);
00783 if(len != 4) {
00784 throw error("Remote host disconnected",*i);
00785 }
00786
00787 const int remote_handle = SDLNet_Read32(buf);
00788 set_remote_handle(*i,remote_handle);
00789
00790 continue;
00791 }
00792
00793 waiting_sockets.erase(i++);
00794 SDLNet_TCP_DelSocket(socket_set,sock);
00795 network_worker_pool::receive_data(sock);
00796 } else {
00797 ++i;
00798 }
00799 }
00800
00801
00802 TCPsocket sock = network_worker_pool::get_received_data(buf);
00803 if (sock == NULL) {
00804 return 0;
00805 }
00806
00807 SDLNet_TCP_AddSocket(socket_set,sock);
00808
00809 connection result = 0;
00810 for(connection_map::const_iterator j = connections.begin(); j != connections.end(); ++j) {
00811 if(j->second.sock == sock) {
00812 result = j->first;
00813 break;
00814 }
00815 }
00816
00817 assert(result != 0);
00818 waiting_sockets.insert(result);
00819 return result;
00820 }
00821
00822
00823
00824
00825 void send_data(const config& cfg, connection connection_num, const bool gzipped)
00826 {
00827 DBG_NW << "in send_data()...\n";
00828
00829 if(cfg.empty()) {
00830 return;
00831 }
00832
00833 if(bad_sockets.count(connection_num) || bad_sockets.count(0)) {
00834 return;
00835 }
00836
00837
00838 if(!connection_num) {
00839 DBG_NW << "sockets: " << sockets.size() << "\n";
00840 for(sockets_list::const_iterator i = sockets.begin();
00841 i != sockets.end(); ++i) {
00842 DBG_NW << "server socket: " << server_socket << "\ncurrent socket: " << *i << "\n";
00843 send_data(cfg,*i, gzipped);
00844 }
00845 return;
00846 }
00847
00848 const connection_map::iterator info = connections.find(connection_num);
00849 if (info == connections.end()) {
00850 ERR_NW << "Error: socket: " << connection_num
00851 << "\tnot found in connection_map. Not sending...\n";
00852 return;
00853 }
00854
00855 LOG_NW << "SENDING to: " << connection_num << ": " << cfg;
00856 network_worker_pool::queue_data(info->second.sock, cfg, gzipped);
00857 }
00858
00859 void send_raw_data(const char* buf, int len, connection connection_num)
00860 {
00861 if(len == 0) {
00862 return;
00863 }
00864
00865 if(bad_sockets.count(connection_num) || bad_sockets.count(0)) {
00866 return;
00867 }
00868
00869 if(!connection_num) {
00870 for(sockets_list::const_iterator i = sockets.begin();
00871 i != sockets.end(); ++i) {
00872 send_raw_data(buf, len, connection_num);
00873 }
00874 return;
00875 }
00876
00877 const connection_map::iterator info = connections.find(connection_num);
00878 if (info == connections.end()) {
00879 ERR_NW << "Error: socket: " << connection_num
00880 << "\tnot found in connection_map. Not sending...\n";
00881 return;
00882 }
00883
00884 network_worker_pool::queue_raw_data(info->second.sock, buf, len);
00885 }
00886
00887 void process_send_queue(connection, size_t)
00888 {
00889 check_error();
00890 }
00891
00892
00893 void send_data_all_except(const config& cfg, connection connection_num, const bool gzipped)
00894 {
00895 for(sockets_list::const_iterator i = sockets.begin(); i != sockets.end(); ++i) {
00896 if(*i == connection_num) {
00897 continue;
00898 }
00899
00900 send_data(cfg,*i, gzipped);
00901 }
00902 }
00903
00904 std::string ip_address(connection connection_num)
00905 {
00906 std::stringstream str;
00907 const IPaddress* const ip = SDLNet_TCP_GetPeerAddress(get_socket(connection_num));
00908 if(ip != NULL) {
00909 const unsigned char* buf = reinterpret_cast<const unsigned char*>(&ip->host);
00910 for(int i = 0; i != sizeof(ip->host); ++i) {
00911 str << int(buf[i]);
00912 if(i+1 != sizeof(ip->host)) {
00913 str << '.';
00914 }
00915 }
00916
00917 }
00918
00919 return str.str();
00920 }
00921
00922 statistics get_send_stats(connection handle)
00923 {
00924 return network_worker_pool::get_current_transfer_stats(handle == 0 ? get_socket(sockets.back()) : get_socket(handle)).first;
00925 }
00926 statistics get_receive_stats(connection handle)
00927 {
00928 return network_worker_pool::get_current_transfer_stats(handle == 0 ? get_socket(sockets.back()) : get_socket(handle)).second;
00929 }
00930
00931 }