int silc_net_udp_send(SilcStream stream, const char *remote_ip_addr, int remote_port, const unsigned char *data, SilcUInt32 data_len) { SilcSocketStream sock = stream; SilcSockaddr remote; int ret; SILC_LOG_DEBUG(("Sending data to UDP socket %d", sock->sock)); /* Set sockaddr */ if (!silc_net_set_sockaddr(&remote, remote_ip_addr, remote_port)) return -2; /* Send */ ret = sendto(sock->sock, data, data_len, 0, &remote.sa, SIZEOF_SOCKADDR(remote)); if (ret < 0) { if (errno == EAGAIN || errno == EINTR) { SILC_LOG_DEBUG(("Could not send immediately, will do it later")); silc_schedule_set_listen_fd(sock->schedule, sock->sock, SILC_TASK_READ | SILC_TASK_WRITE, FALSE); return -1; } SILC_LOG_DEBUG(("Cannot send to UDP socket: %s", strerror(errno))); silc_schedule_unset_listen_fd(sock->schedule, sock->sock); sock->sock_error = errno; return -2; } SILC_LOG_DEBUG(("Sent data %d bytes", ret)); if (silc_schedule_get_fd_events(sock->schedule, sock->sock) & SILC_TASK_WRITE) silc_schedule_set_listen_fd(sock->schedule, sock->sock, SILC_TASK_READ, FALSE); return ret; }
SilcStream silc_net_udp_connect(const char *local_ip_addr, int local_port, const char *remote_ip_addr, int remote_port, SilcSchedule schedule) { SilcSymbianSocket *s; SilcStream stream; TInetAddr local, remote; TRequestStatus status; RSocket *sock = NULL; RSocketServ *ss = NULL; TInt ret; SILC_LOG_DEBUG(("Creating UDP stream")); if (!schedule) { schedule = silc_schedule_get_global(); if (!schedule) { silc_set_errno(SILC_ERR_INVALID_ARGUMENT); goto err; } } SILC_LOG_DEBUG(("Binding to local address %s", local_ip_addr ? local_ip_addr : "0.0.0.0")); sock = new RSocket; if (!sock) goto err; ss = new RSocketServ; if (!ss) goto err; /* Open socket server */ ret = ss->Connect(); if (ret != KErrNone) goto err; #ifdef SILC_THREADS /* Make our socket shareable between threads */ ss->ShareAuto(); #endif /* SILC_THREADS */ /* Get local bind address */ if (!silc_net_set_sockaddr(&local, local_ip_addr, local_port)) goto err; /* Create the socket */ ret = sock->Open(*ss, KAfInet, KSockDatagram, KProtocolInetUdp); if (ret != KErrNone) { SILC_LOG_ERROR(("Cannot create socket")); goto err; } /* Set the socket options */ sock->SetOpt(KSoReuseAddr, KSolInetIp, 1); /* Bind the listener socket */ ret = sock->Bind(local); if (ret != KErrNone) { SILC_LOG_DEBUG(("Cannot bind socket")); goto err; } /* Set to connected state if remote address is provided. */ if (remote_ip_addr && remote_port) { if (silc_net_set_sockaddr(&remote, remote_ip_addr, remote_port)) { sock->Connect(remote, status); if (status != KErrNone) { SILC_LOG_DEBUG(("Cannot connect UDP stream")); goto err; } } } /* Encapsulate into socket stream */ s = silc_create_symbian_socket(sock, ss); if (!s) goto err; stream = silc_socket_udp_stream_create((SilcSocket)s, local_ip_addr ? silc_net_is_ip6(local_ip_addr) : FALSE, remote_ip_addr ? TRUE : FALSE, schedule); if (!stream) goto err; SILC_LOG_DEBUG(("UDP stream created, fd=%d", sock)); return stream; err: if (sock) delete sock; if (ss) { ss->Close(); delete ss; } return NULL; }
SilcAsyncOperation silc_net_tcp_connect(const char *local_ip_addr, const char *remote_ip_addr, int remote_port, SilcSchedule schedule, SilcNetCallback callback, void *context) { SilcSymbianTCPConnect *conn; TInetAddr local, remote; SilcResult status; TInt ret; if (!schedule) { schedule = silc_schedule_get_global(); if (!schedule) { silc_set_errno(SILC_ERR_INVALID_ARGUMENT); return NULL; } } if (!remote_ip_addr || remote_port < 1 || !callback) { silc_set_errno(SILC_ERR_INVALID_ARGUMENT); return NULL; } SILC_LOG_DEBUG(("Creating connection to host %s port %d", remote_ip_addr, remote_port)); conn = new SilcSymbianTCPConnect; if (!conn) { callback(SILC_ERR_OUT_OF_MEMORY, NULL, context); return NULL; } conn->schedule = schedule; conn->callback = callback; conn->context = context; conn->port = remote_port; conn->remote = strdup(remote_ip_addr); if (!conn->remote) { status = SILC_ERR_OUT_OF_MEMORY; goto err; } /* Allocate socket */ conn->sock = new RSocket; if (!conn->sock) { status = SILC_ERR_OUT_OF_MEMORY; goto err; } /* Allocate socket server */ conn->ss = new RSocketServ; if (!conn->ss) { status = SILC_ERR_OUT_OF_MEMORY; goto err; } /* Connect to socket server */ ret = conn->ss->Connect(); if (ret != KErrNone) { SILC_LOG_ERROR(("Error connecting to socket server, error %d", ret)); status = SILC_ERR; goto err; } #ifdef SILC_THREADS /* Make our socket shareable between threads */ conn->ss->ShareAuto(); #endif /* SILC_THREADS */ /* Start async operation */ conn->op = silc_async_alloc(silc_net_connect_abort, NULL, (void *)conn); if (!conn->op) { status = SILC_ERR_OUT_OF_MEMORY; goto err; } /* Do host lookup */ if (!silc_net_gethostbyname(remote_ip_addr, FALSE, conn->remote_ip, sizeof(conn->remote_ip))) { SILC_LOG_ERROR(("Network (%s) unreachable: could not resolve the " "host", conn->remote)); status = SILC_ERR_UNREACHABLE; goto err; } /* Create the connection socket */ ret = conn->sock->Open(*conn->ss, KAfInet, KSockStream, KProtocolInetTcp); if (ret != KErrNone) { SILC_LOG_ERROR(("Cannot create socket, error %d", ret)); status = SILC_ERR; goto err; } /* Set appropriate options */ conn->sock->SetOpt(KSoTcpNoDelay, KSolInetTcp, 1); conn->sock->SetOpt(KSoTcpKeepAlive, KSolInetTcp, 1); /* Bind to the local address if provided */ if (local_ip_addr) if (silc_net_set_sockaddr(&local, local_ip_addr, 0)) conn->sock->Bind(local); /* Connect to the host */ if (!silc_net_set_sockaddr(&remote, conn->remote_ip, remote_port)) { SILC_LOG_ERROR(("Cannot connect (cannot set address)")); status = SILC_ERR; goto err; } conn->Connect(remote); SILC_LOG_DEBUG(("Connection operation in progress")); return conn->op; err: if (conn->ss) { conn->ss->Close(); delete conn->ss; } if (conn->sock) delete conn->sock; if (conn->remote) silc_free(conn->remote); if (conn->op) silc_async_free(conn->op); callback(status, NULL, context); delete conn; return NULL; }
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; }
SilcStream silc_net_udp_connect(const char *local_ip_addr, int local_port, const char *remote_ip_addr, int remote_port, SilcSchedule schedule) { SilcStream stream; SilcSockaddr server; int sock = -1, rval; const char *ipany = "0.0.0.0"; SILC_LOG_DEBUG(("Creating UDP stream")); if (!schedule) goto err; /* Bind to local addresses */ SILC_LOG_DEBUG(("Binding to local address %s", local_ip_addr ? local_ip_addr : ipany)); /* Set sockaddr for server */ if (!silc_net_set_sockaddr(&server, local_ip_addr ? local_ip_addr : ipany, local_port)) goto err; /* Create the socket */ sock = socket(server.sin.sin_family, SOCK_DGRAM, 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))); goto err; } #ifdef SO_REUSEPORT rval = silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEPORT, 1); if (rval < 0) { SILC_LOG_ERROR(("Cannot set socket options: %s", strerror(errno))); goto err; } #endif /* SO_REUSEPORT */ /* Bind the listener socket */ rval = bind(sock, &server.sa, SIZEOF_SOCKADDR(server)); if (rval < 0) { SILC_LOG_DEBUG(("Cannot bind socket: %s", strerror(errno))); goto err; } /* Set to connected state if remote address is provided. */ if (remote_ip_addr && remote_port) { if (!silc_net_set_sockaddr(&server, remote_ip_addr, remote_port)) goto err; rval = connect(sock, &server.sa, SIZEOF_SOCKADDR(server)); if (rval < 0) { SILC_LOG_DEBUG(("Cannot connect UDP stream: %s", strerror(errno))); goto err; } } /* Set send and receive buffer size */ #ifdef SO_SNDBUF rval = silc_net_set_socket_opt(sock, SOL_SOCKET, SO_SNDBUF, 765535); if (rval < 0) { rval = silc_net_set_socket_opt(sock, SOL_SOCKET, SO_SNDBUF, 65535); if (rval < 0) { SILC_LOG_ERROR(("Cannot set socket options: %s", strerror(errno))); goto err; } } #endif /* SO_SNDBUF */ #ifdef SO_RCVBUF rval = silc_net_set_socket_opt(sock, SOL_SOCKET, SO_RCVBUF, 765535); if (rval < 0) { rval = silc_net_set_socket_opt(sock, SOL_SOCKET, SO_RCVBUF, 65535); if (rval < 0) { SILC_LOG_ERROR(("Cannot set socket options: %s", strerror(errno))); goto err; } } #endif /* SO_RCVBUF */ /* Encapsulate into socket stream */ stream = silc_socket_udp_stream_create(sock, local_ip_addr ? silc_net_is_ip6(local_ip_addr) : FALSE, remote_ip_addr ? TRUE : FALSE, schedule); if (!stream) goto err; SILC_LOG_DEBUG(("UDP stream created, fd=%d", sock)); return stream; err: if (sock != -1) close(sock); 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; }