SilcNetListener silc_net_tcp_create_listener2(const char *local_ip_addr, int *ports, SilcUInt32 port_count, SilcBool ignore_port_error, SilcBool lookup, SilcBool require_fqdn, SilcSchedule schedule, SilcNetCallback callback, void *context) { SilcNetListener listener = NULL; SilcSymbianTCPListener *l = NULL; TInetAddr server; TInt ret; int i; SILC_LOG_DEBUG(("Creating TCP listener")); if (!schedule) { schedule = silc_schedule_get_global(); if (!schedule) { silc_set_errno(SILC_ERR_INVALID_ARGUMENT); goto err; } } if (!callback) { silc_set_errno(SILC_ERR_INVALID_ARGUMENT); goto err; } listener = (SilcNetListener)silc_calloc(1, sizeof(*listener)); if (!listener) { callback(SILC_ERR_OUT_OF_MEMORY, NULL, context); return NULL; } listener->schedule = schedule; listener->callback = callback; listener->context = context; listener->require_fqdn = require_fqdn; listener->lookup = lookup; if (port_count > 0) { listener->socks = (SilcSocket *)silc_calloc(port_count, sizeof(*listener->socks)); if (!listener->socks) { callback(SILC_ERR_OUT_OF_MEMORY, NULL, context); return NULL; } } else { listener->socks = (SilcSocket *)silc_calloc(1, sizeof(*listener->socks)); if (!listener->socks) { callback(SILC_ERR_OUT_OF_MEMORY, NULL, context); return NULL; } port_count = 1; } /* Bind to ports */ for (i = 0; i < port_count; i++) { SILC_LOG_DEBUG(("Binding to local address %s:%d", local_ip_addr ? local_ip_addr : "0.0.0.0", ports ? ports[i] : 0)); l = new SilcSymbianTCPListener; if (!l) goto err; /* Connect to socket server */ ret = l->ss.Connect(); if (ret != KErrNone) goto err; #ifdef SILC_THREADS /* Make our socket shareable between threads */ l->ss.ShareAuto(); #endif /* SILC_THREADS */ /* Set listener address */ if (!silc_net_set_sockaddr(&server, local_ip_addr, ports ? ports[i] : 0)) { if (ignore_port_error) { delete l; continue; } goto err; } /* Create the socket */ ret = l->sock.Open(l->ss, KAfInet, KSockStream, KProtocolInetTcp); if (ret != KErrNone) { if (ignore_port_error) { delete l; continue; } SILC_LOG_ERROR(("Cannot create socket, error %d", ret)); goto err; } /* Set the socket options */ ret = l->sock.SetOpt(KSoReuseAddr, KSolInetIp, 1); if (ret != KErrNone) { if (ignore_port_error) { delete l; continue; } SILC_LOG_ERROR(("Cannot set socket options, error %d", ret)); goto err; } /* Bind the listener socket */ ret = l->sock.Bind(server); if (ret != KErrNone) { if (ignore_port_error) { delete l; continue; } SILC_LOG_DEBUG(("Cannot bind socket, error %d", ret)); goto err; } /* Specify that we are listenning */ ret = l->sock.Listen(5); if (ret != KErrNone) { if (ignore_port_error) { delete l; continue; } SILC_LOG_ERROR(("Cannot set socket listenning, error %d", ret)); goto err; } l->Listen(); l->listener = listener; listener->socks[i] = (SilcSocket)l; listener->socks_count++; } if (ignore_port_error && !listener->socks_count) { l = NULL; goto err; } SILC_LOG_DEBUG(("TCP listener created")); return listener; err: if (l) delete l; if (callback) callback(SILC_ERR, NULL, context); if (listener) silc_net_close_listener(listener); return NULL; }
SilcNetListener silc_net_tcp_create_listener(const char **local_ip_addr, SilcUInt32 local_ip_count, int port, SilcBool lookup, SilcBool require_fqdn, SilcSchedule schedule, SilcNetCallback callback, void *context) { SilcNetListener listener = NULL; SilcSockaddr server; int i, sock, rval; const char *ipany = "0.0.0.0"; SILC_LOG_DEBUG(("Creating TCP listener")); if (port < 0 || !schedule || !callback) goto err; listener = silc_calloc(1, sizeof(*listener)); if (!listener) return NULL; listener->schedule = schedule; listener->callback = callback; listener->context = context; listener->require_fqdn = require_fqdn; listener->lookup = lookup; if (local_ip_count > 0) { listener->socks = silc_calloc(local_ip_count, sizeof(*listener->socks)); if (!listener->socks) return NULL; } else { listener->socks = silc_calloc(1, sizeof(*listener->socks)); if (!listener->socks) return NULL; local_ip_count = 1; } /* Bind to local addresses */ for (i = 0; i < local_ip_count; i++) { SILC_LOG_DEBUG(("Binding to local address %s:%d", local_ip_addr ? local_ip_addr[i] : ipany, port)); /* Set sockaddr for server */ if (!silc_net_set_sockaddr(&server, local_ip_addr ? local_ip_addr[i] : ipany, port)) goto err; /* Create the socket */ sock = socket(server.sin.sin_family, SOCK_STREAM, 0); if (sock < 0) { SILC_LOG_ERROR(("Cannot create socket: %s", strerror(errno))); goto err; } /* Set the socket options */ rval = silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 1); if (rval < 0) { SILC_LOG_ERROR(("Cannot set socket options: %s", strerror(errno))); close(sock); goto err; } /* Bind the listener socket */ rval = bind(sock, &server.sa, SIZEOF_SOCKADDR(server)); if (rval < 0) { SILC_LOG_ERROR(("Cannot bind socket: %s", strerror(errno))); close(sock); goto err; } /* Specify that we are listenning */ rval = listen(sock, 64); if (rval < 0) { SILC_LOG_ERROR(("Cannot set socket listenning: %s", strerror(errno))); close(sock); goto err; } /* Set the server socket to non-blocking mode */ silc_net_set_socket_nonblock(sock); /* Schedule for incoming connections */ silc_schedule_task_add_fd(schedule, sock, silc_net_accept, listener); SILC_LOG_DEBUG(("TCP listener created, fd=%d", sock)); listener->socks[i] = sock; listener->socks_count++; } return listener; err: if (listener) silc_net_close_listener(listener); return NULL; }