int net_host_broadcast_thread(void *arg) { char ip[32],err_str[256]; unsigned char *uc_ptr; unsigned long r_addr; d3socket sock; // use broadcast err_str to flag if errors occured broadcast_listen_err_str[0]=0x0; // create host socket broadcast_listen_socket=net_udp_open_socket(); if (broadcast_listen_socket==D3_NULL_SOCKET) { strcpy(broadcast_listen_err_str,"Networking: Unable to open socket"); broadcast_listen_complete=TRUE; return(0); } net_socket_blocking(broadcast_listen_socket,TRUE); // bind to the "any" IP to gather // any broadcast messages if (!net_udp_bind_broadcast(broadcast_listen_socket,net_port_host_broadcast,broadcast_listen_err_str)) { net_close_socket(&broadcast_listen_socket); broadcast_listen_complete=TRUE; return(0); } // listener is OK, free thread to run independantly broadcast_listen_complete=TRUE; // start listening while (TRUE) { r_addr=net_udp_receive_broadcast(broadcast_listen_socket); if (r_addr==-1) break; // connect and reply that we are a server uc_ptr=(unsigned char*)&r_addr; sock=net_open_socket(); if (sock==D3_NULL_SOCKET) continue; uc_ptr=(unsigned char*)&r_addr; sprintf(ip,"%d.%d.%d.%d",uc_ptr[0],uc_ptr[1],uc_ptr[2],uc_ptr[3]); if (net_connect_block(sock,ip,net_port_host_broadcast_reply,client_timeout_wait_seconds,err_str)) { net_host_client_handle_info(sock); } net_close_socket(&sock); } return(0); }
/* Opens and connects socket */ int net_open_socket(char *host, char *port) { int sd; struct addrinfo *serverinfo; serverinfo = net_resolve(host, port); sd = socket(serverinfo->ai_family, serverinfo->ai_socktype, serverinfo->ai_protocol); if(sd < 0) { #ifdef _WIN32 WSACleanup(); #endif freeaddrinfo(serverinfo); error("Error: cannot create socket.\n"); } if(connect(sd, serverinfo->ai_addr, serverinfo->ai_addrlen) != 0) { net_close_socket(sd); fprintf(stderr, "Error: connection failed (%s).\n", host); freeaddrinfo(serverinfo); exit(-1); } freeaddrinfo(serverinfo); return sd; }
void am_net_diconnect(am_net_t *n) { if (n != NULL) { set_exit_event(n->de); net_close_ssl(n); net_close_socket(n->sock); n->sock = INVALID_SOCKET; } }
void net_host_broadcast_shutdown(void) { // did broadcast listener never start? if (broadcast_listen_socket==D3_NULL_SOCKET) return; // shutdown socket and then wait for termination net_close_socket(&broadcast_listen_socket); SDL_WaitThread(broadcast_listen_thread,NULL); }
int net_host_thread(void *arg) { // use host err_str to flag if errors occured host_err_str[0]=0x0; // create host socket host_socket=net_open_udp_socket(); if (host_socket==D3_NULL_SOCKET) { strcpy(host_err_str,"Hosting: Unable to open socket"); host_complete=TRUE; return(0); } // we'll let the socket block for us net_socket_blocking(host_socket,TRUE); // bind -- use any IP on this machine to // get traffic if (!net_bind_any(host_socket,net_port_host,host_err_str)) { net_close_socket(&host_socket); host_complete=TRUE; return(0); } // host is OK, free thread to run independantly host_complete=TRUE; // begin waiting for messages while (TRUE) { // exiting? if (host_start_shutdown) break; // feed the queues from the socket // if there's an error, break out of loop // and cancel network game if (!net_queue_feed(host_socket,&host_queue)) break; // always wait a little to not flood this thread usleep(100000); } return(0); }
void net_host_shutdown(void) { // did host never start? if (host_socket==D3_NULL_SOCKET) return; // trigger the shutdown and wait host_start_shutdown=TRUE; SDL_WaitThread(host_thread,NULL); // shutdown socket and free queue net_close_socket(&host_socket); net_queue_shutdown(&host_queue); }
int main(int argc, char *argv[]) { int opt, ret = 0; int terminal_mode = 0; char *host = NULL; char *pass = ""; char *port = "25575"; if(argc < 2) usage(); opterr = 1; /* default error handler enabled */ while((opt = getopt(argc, argv, "tcshH:p:P:i")) != -1) { switch(opt) { case 'H': host = optarg; break; case 'P': port = optarg; break; case 'p': pass = optarg; break; case 'C': case 'c': print_colors = 0; break; case 'S': case 's': silent_mode = 1; break; case 'T': case 't': case 'I': case 'i': terminal_mode = 1; break; case 'h': case '?': /* if(optopt == 'P' || optopt == 'H' || optopt == 'p') fprintf (stderr, "Option -%c requires an argument.\n\n", optopt); */ /* else fprintf (stderr, "Unknown option -%c\n\n", optopt); */ usage(); break; default: abort(); } } if(host == NULL) { fputs("Host not defined. Check -H flag.\n\n", stdout); usage(); } if(optind == argc && terminal_mode == 0) { fputs("No commands specified.\n\n", stdout); usage(); } /* safety features to prevent "IO: Connection reset" bug on the server side */ atexit(&exit_proc); signal(SIGABRT, &sighandler); signal(SIGTERM, &sighandler); signal(SIGINT, &sighandler); #ifdef _WIN32 net_init_WSA(); console_handle = GetStdHandle(STD_OUTPUT_HANDLE); if(console_handle == INVALID_HANDLE_VALUE) console_handle = NULL; #endif /* open socket */ rsock = net_open_socket(host, port); /* auth & commands */ if(rcon_auth(rsock, pass)) { if(terminal_mode) ret = run_terminal_mode(rsock); else ret = run_commands(argc, argv); } else /* auth failed */ { ret = -1; fprintf(stdout, "Authentication failed!\n"); } /* cleanup */ net_close_socket(rsock); rsock = -1; return ret; }
/* safety stuff (windows is still misbehaving) */ void exit_proc(void) { if(rsock != -1) net_close_socket(rsock); }
static void *net_async_connect(void *arg) { am_net_t *n = (am_net_t *) arg; static const char *thisfunc = "net_async_connect():"; struct in6_addr serveraddr; struct addrinfo *rp, hints; int err = 0, on = 1; char port[7]; am_timer_t tmr; memset(&hints, 0, sizeof (struct addrinfo)); hints.ai_flags = AI_NUMERICSERV; hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; err = INETPTON(AF_INET, n->uv.host, &serveraddr); if (err == 1) { hints.ai_family = AF_INET; hints.ai_flags |= AI_NUMERICHOST; } else { err = INETPTON(AF_INET6, n->uv.host, &serveraddr); if (err == 1) { hints.ai_family = AF_INET6; hints.ai_flags |= AI_NUMERICHOST; } } snprintf(port, sizeof (port), "%d", n->uv.port); am_timer_start(&tmr); if ((err = getaddrinfo(n->uv.host, port, &hints, &n->ra)) != 0) { n->error = AM_EHOSTUNREACH; am_timer_stop(&tmr); am_timer_report(n->instance_id, &tmr, "getaddrinfo"); set_event(n->ce); return NULL; } am_timer_stop(&tmr); am_timer_report(n->instance_id, &tmr, "getaddrinfo"); n->error = 0; for (rp = n->ra; rp != NULL; rp = rp->ai_next) { if (rp->ai_family != AF_INET && rp->ai_family != AF_INET6 && rp->ai_socktype != SOCK_STREAM && rp->ai_protocol != IPPROTO_TCP) continue; if ((n->sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) == INVALID_SOCKET) { AM_LOG_ERROR(n->instance_id, "%s: cannot create socket while connecting to %s:%d", thisfunc, n->uv.host, n->uv.port); net_log_error(n->instance_id, net_error()); continue; } if (setsockopt(n->sock, IPPROTO_TCP, TCP_NODELAY, (void *) &on, sizeof (on)) < 0) { net_log_error(n->instance_id, net_error()); } if (setsockopt(n->sock, SOL_SOCKET, SO_REUSEADDR, (void *) &on, sizeof (on)) < 0) { net_log_error(n->instance_id, net_error()); } #ifdef SO_NOSIGPIPE if (setsockopt(n->sock, SOL_SOCKET, SO_NOSIGPIPE, (void *) &on, sizeof (on)) < 0) { net_log_error(n->instance_id, net_error()); } #endif if (set_nonblocking(n, 1) != 0) { n->error = AM_EPERM; continue; } err = connect(n->sock, rp->ai_addr, (SOCKLEN_T) rp->ai_addrlen); if (err == 0) { AM_LOG_DEBUG(n->instance_id, "%s: connected to %s:%d (%s)", thisfunc, n->uv.host, n->uv.port, rp->ai_family == AF_INET ? "IPv4" : "IPv6"); n->error = 0; if (n->uv.ssl) { net_connect_ssl(n); if (n->ssl.error != AM_SUCCESS) { AM_LOG_ERROR(n->instance_id, "%s: SSL/TLS connection to %s:%d (%s) failed (%s)", thisfunc, n->uv.host, n->uv.port, rp->ai_family == AF_INET ? "IPv4" : "IPv6", am_strerror(n->ssl.error)); net_close_socket(n->sock); n->sock = INVALID_SOCKET; n->error = n->ssl.error; break; } } net_async_poll(n); break; } if (err == INVALID_SOCKET && net_in_progress(net_error())) { #ifdef _WIN32 WSAPOLLFD fds[1]; #else struct pollfd fds[1]; #endif memset(fds, 0, sizeof (fds)); fds[0].fd = n->sock; fds[0].events = connect_ev; fds[0].revents = 0; err = sockpoll(fds, 1, n->timeout > 0 ? n->timeout * 1000 : -1); if (err > 0 && fds[0].revents & connected_ev) { int pe = 0; SOCKLEN_T pe_sz = sizeof (pe); err = getsockopt(n->sock, SOL_SOCKET, SO_ERROR, (char *) &pe, &pe_sz); if (err == 0 && pe == 0) { AM_LOG_DEBUG(n->instance_id, "%s: connected to %s:%d (%s)", thisfunc, n->uv.host, n->uv.port, rp->ai_family == AF_INET ? "IPv4" : "IPv6"); n->error = 0; if (n->uv.ssl) { net_connect_ssl(n); if (n->ssl.error != AM_SUCCESS) { AM_LOG_ERROR(n->instance_id, "%s: SSL/TLS connection to %s:%d (%s) failed (%s)", thisfunc, n->uv.host, n->uv.port, rp->ai_family == AF_INET ? "IPv4" : "IPv6", am_strerror(n->ssl.error)); net_close_socket(n->sock); n->sock = INVALID_SOCKET; n->error = n->ssl.error; break; } } net_async_poll(n); break; } net_log_error(n->instance_id, pe); n->error = AM_ECONNREFUSED; } else if (err == 0) { AM_LOG_WARNING(n->instance_id, "%s: timeout connecting to %s:%d (%s)", thisfunc, n->uv.host, n->uv.port, rp->ai_family == AF_INET ? "IPv4" : "IPv6"); n->error = AM_ETIMEDOUT; } else { int pe = 0; SOCKLEN_T pe_sz = sizeof (pe); err = getsockopt(n->sock, SOL_SOCKET, SO_ERROR, (char *) &pe, &pe_sz); n->error = AM_ETIMEDOUT; break; } } net_close_socket(n->sock); n->sock = INVALID_SOCKET; } if (n->error != 0) { set_event(n->ce); } return NULL; }