int32 network_addlistener(bool v6, const char *addr, uint16 port) { SESSION *s; int optval, fd; #if !defined(ENABLE_IPV6) if(v6 == true) { ShowError(read_message("Source.common.network_addlistener"), (v6==true?'t':'f'), addr, port); return -1; } #endif #ifdef ENABLE_IPV6 if(v6 == true) fd = socket(AF_INET6, SOCK_STREAM, 0); else #endif fd = socket(AF_INET, SOCK_STREAM, 0); // Error? if(fd == -1) { ShowError(read_message("Source.common.network_addlistener2"), (v6==true?'t':'f'), addr, port, errno, strerror(errno)); return -1; } // Too many connections? if(fd >= MAXCONN) { ShowError(read_message("Source.common.network_addlistener3"), (v6==true?'t':'f'), addr, port, MAXCONN); close(fd); return -1; } s = &g_Session[fd]; if(s->type != NST_FREE) { // additional checks.. :) ShowError(read_message("Source.common.network_addlistener4"), (v6==true?'t':'f'), addr, port, fd); close(fd); return -1; } // Fill ip addr structs #ifdef ENABLE_IPV6 if(v6 == true) { memset(&s->addr.v6, 0x00, sizeof(s->addr.v6)); s->addr.v6.sin6_family = AF_INET6; s->addr.v6.sin6_port = htons(port); if(inet_pton(AF_INET6, addr, &s->addr.v6.sin6_addr) != 1) { ShowError(read_message("Source.common.network_addlistener5"), (v6==true?'t':'f'), addr, port); close(fd); return -1; } } else { #endif memset(&s->addr.v4, 0x00, sizeof(s->addr.v4)); s->addr.v4.sin_family = AF_INET; s->addr.v4.sin_port = htons(port); s->addr.v4.sin_addr.s_addr = inet_addr(addr); #ifdef ENABLE_IPV6 } #endif // if OS has support for SO_REUSEADDR, apply the flag // so the address could be used when there're still time_wait sockets outstanding from previous application run. #ifdef SO_REUSEADDR optval=1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); #endif // Bind #ifdef ENABLE_IPV6 if(v6 == true) { if(bind(fd, (struct sockaddr *)&s->addr.v6, sizeof(s->addr.v6)) == -1) { ShowError(read_message("Source.common.add_listener6"), (v6==true?'t':'f'), addr, port, errno, strerror(errno)); close(fd); return -1; } } else { #endif if(bind(fd, (struct sockaddr *)&s->addr.v4, sizeof(s->addr.v4)) == -1) { ShowError(read_message("Source.common.add_listener6"), (v6==true?'t':'f'), addr, port, errno, strerror(errno)); close(fd); return -1; } #ifdef ENABLE_IPV6 } #endif if(listen(fd, l_ListenBacklog) == -1) { ShowError(read_message("Source.common.add_listener7"), (v6==true?'t':'f'), addr, port, errno, strerror(errno)); close(fd); return -1; } // Set to nonblock! if(_setnonblock(fd) == false) { ShowError(read_message("Source.common.addlistener8"), (v6==true?'t':'f'), addr, port, errno, strerror(errno)); close(fd); return -1; } // Rgister @ evdp. if(evdp_addlistener(fd, &s->evdp_data) != true) { ShowError(read_message("Source.common.addlistener9"), (v6==true?'t':'f'), addr, port); close(fd); return -1; } // Apply flags on Session array for this conneciton. if(v6 == true) s->v6 = true; else s->v6 = false; s->type = NST_LISTENER; s->onRecv = _network_accept; ShowStatus(read_message("Source.common.add_listener10"), addr, port, (v6==true ? "(ipv6)":"(ipv4)")); return fd; }//end: network_addlistener()
int32 network_addlistener(bool v6, const char *addr, uint16 port){ SESSION *s; int optval, fd; #if !defined(ENABLE_IPV6) if(v6 == true){ ShowError("network_addlistener(%c, '%s', %u): this release has no IPV6 support.\n", (v6==true?'t':'f'), addr, port); return -1; } #endif #ifdef ENABLE_IPV6 if(v6 == true) fd = socket(AF_INET6, SOCK_STREAM, 0); else #endif fd = socket(AF_INET, SOCK_STREAM, 0); // Error? if(fd == -1){ ShowError("network_addlistener(%c, '%s', %u): socket() failed (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno)); return -1; } // Too many connections? if(fd >= MAXCONN){ ShowError("network_addlistener(%c, '%s', %u): cannot create listener, exceeds more than supported connections (%u).\n", (v6==true?'t':'f'), addr, port, MAXCONN); close(fd); return -1; } s = &g_Session[fd]; if(s->type != NST_FREE){ // additional checks.. :) ShowError("network_addlistener(%c, '%s', %u): failed, got fd #%u which is already in use in local session table?!\n", (v6==true?'t':'f'), addr, port, fd); close(fd); return -1; } // Fill ip addr structs #ifdef ENABLE_IPV6 if(v6 == true){ memset(&s->addr.v6, 0x00, sizeof(s->addr.v6)); s->addr.v6.sin6_family = AF_INET6; s->addr.v6.sin6_port = htons(port); if(inet_pton(AF_INET6, addr, &s->addr.v6.sin6_addr) != 1){ ShowError("network_addlistener(%c, '%s', %u): failed to parse the given IPV6 address.\n", (v6==true?'t':'f'), addr, port); close(fd); return -1; } }else{ #endif memset(&s->addr.v4, 0x00, sizeof(s->addr.v4)); s->addr.v4.sin_family = AF_INET; s->addr.v4.sin_port = htons(port); s->addr.v4.sin_addr.s_addr = inet_addr(addr); #ifdef ENABLE_IPV6 } #endif // if OS has support for SO_REUSEADDR, apply the flag // so the address could be used when there're still time_wait sockets outstanding from previous application run. #ifdef SO_REUSEADDR optval=1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); #endif // Bind #ifdef ENABLE_IPV6 if(v6 == true){ if( bind(fd, (struct sockaddr*)&s->addr.v6, sizeof(s->addr.v6)) == -1) { ShowError("network_addlistener(%c, '%s', %u): bind failed (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno)); close(fd); return -1; } }else{ #endif if( bind(fd, (struct sockaddr*)&s->addr.v4, sizeof(s->addr.v4)) == -1) { ShowError("network_addlistener(%c, '%s', %u): bind failed (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno)); close(fd); return -1; } #ifdef ENABLE_IPV6 } #endif if( listen(fd, l_ListenBacklog) == -1){ ShowError("network_addlistener(%c, '%s', %u): listen failed (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno)); close(fd); return -1; } // Set to nonblock! if(_setnonblock(fd) == false){ ShowError("network_addlistener(%c, '%s', %u): cannot set to nonblock (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno)); close(fd); return -1; } // Rgister @ evdp. if( evdp_addlistener(fd, &s->evdp_data) != true){ ShowError("network_addlistener(%c, '%s', %u): eventdispatcher subsystem returned an error.\n", (v6==true?'t':'f'), addr, port); close(fd); return -1; } // Apply flags on Session array for this conneciton. if(v6 == true) s->v6 = true; else s->v6 = false; s->type = NST_LISTENER; s->onRecv = _network_accept; ShowStatus("Added Listener on '%s':%u\n", addr, port, (v6==true ? "(ipv6)":"(ipv4)") ); return fd; }//end: network_addlistener()