#include <unistd.h>
#include <forb/config.h>
#include "discovery.h"
+#include <stdlib.h>
+#include <netinet/tcp.h>
+#include "iop.h" /* FIXME: Sending hello should be handled in IOP layer */
/**
* @file proto_inet.c
return ret;
}
-static struct inet_peer *
+static int
+setnonblocking(int fd);
+
+static int
+setnodelay(int fd)
+{
+ int ret = 0;
+#if 0 /* For nice graphs in benchmarks */
+ int yes = 1;
+ ret = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes));
+ if (ret < 0) {
+ ul_logerr("setsockopt(TCP_NODELAY): %s\n", strerror(errno));
+ }
+#endif
+ return ret;
+
+}
+
+static int
inet_connect(forb_peer_t *peer)
{
struct inet_peer *ipeer;
if (!addr) {
ul_logerr("No address to connect\n");
- return NULL;
+ goto err;
}
ipeer = forb_malloc(sizeof(*ipeer));
if (!ipeer)
sa.sin_family = AF_INET;
sa.sin_port = addr->port;
sa.sin_addr = addr->addr;
- ul_logdeb("connect to %s:%u\n", inet_ntoa(sa.sin_addr), ntohs(sa.sin_port));
+ ul_logtrash("connect to %s:%u\n", inet_ntoa(sa.sin_addr), ntohs(sa.sin_port));
ret = connect(ipeer->socket, (struct sockaddr*)&sa, sizeof(sa));
if (ret) {
ul_logerr("connect error: %s\n", strerror(errno));
goto err_close;
}
+ setnonblocking(ipeer->socket);
+ setnodelay(ipeer->socket);
+
struct epoll_event ev;
struct inet_port *p = peer->port->desc.proto_priv;
memset(&ev, 0, sizeof(ev));
goto err_close;
}
+ peer->proto_priv = ipeer;
+
+#ifndef TEST /* FIXME: Move hello to IOP, introduce proto connect callback */
+ ret = forb_iop_send_hello_to(peer);
+ if (ret) {
+ goto err_close;
+ }
+#endif
- return ipeer;
+ return 0;
err_close:
close(ipeer->socket);
err_free:
forb_free(ipeer);
err:
- return NULL;
+ return -1;
}
ssize_t ret, sent;
if (!ipeer) {
- ipeer = inet_connect(peer);
- if (!ipeer) {
- return -1;
+ ret = inet_connect(peer);
+ if (ret) {
+ return ret;
}
- peer->proto_priv = ipeer;
-
+ ipeer = peer->proto_priv;
}
sent = 0;
- ul_logdeb("send fd=%d len=%d\n", ipeer->socket, len);
+ ul_logtrash("send fd=%d len=%zu\n", ipeer->socket, len);
do {
ret = send(ipeer->socket, buf, len, 0);
if (ret < 0) {
close(client);
return -1;
}
+ setnodelay(client);
peer = forb_peer_new();
if (peer) {
peer->port = port;
peer->state = FORB_PEER_DISCOVERED;
inet_port_new_peer_insert(p, peer);
- //printf("New connection d=%d\n", client);
} else {
forb_peer_put(peer);
}
forb_peer_put(peer);
port->new_peer = NULL;
}
- ul_logdeb("recv fd=%d disconnect\n", iport->last_recv_fd);
+ ul_logtrash("recv fd=%d disconnect\n", iport->last_recv_fd);
ul_list_for_each(forb_port_peer, port, peer) {
struct inet_peer *ipeer = peer->proto_priv;
if (ipeer && ipeer->socket == iport->last_recv_fd) {
iport->last_recv_fd = -1;
continue;
}
- ul_logdeb("recv fd=%d len=%d\n", iport->last_recv_fd, ret);
+ ul_logtrash("recv fd=%d len=%zd\n", iport->last_recv_fd, ret);
return ret;
}
#else
struct inet_peer *ipeer = peer->proto_priv;
if (ipeer) {
peer->proto_priv = NULL;
- ul_logdeb("destroying peer fd=%d\n", ipeer->socket);
+ ul_logtrash("destroying peer fd=%d\n", ipeer->socket);
close(ipeer->socket);
free(ipeer);
}
#include <fcb.h>
#include <fcb_contact_info.h>
-#include <stdlib.h>
static void inet_register_cb(forb_port_t *port)
{
{
struct ifconf ifc;
struct ifreq *ifr, req[MAX_INTERFACES];
+ char *env;
+ bool loopback = false;
+ int ret;
+ struct in_addr env_addr;
+ env = getenv("FORB_EXTERNAL_IP");
+ if (env) {
+ if (inet_aton(env, &env_addr) == 0) {
+ ul_logerr("Cannot convert FORB_EXTERNAL_IP\n");
+ errno = EINVAL;
+ return -1;
+ }
+ }
ifc.ifc_len = sizeof(req);
ifc.ifc_req = req;
for (ifr = req; ifr < &req[MAX_INTERFACES]; ifr++) {
struct sockaddr_in ia;
memcpy(&ia, &ifr->ifr_addr, sizeof(ia));
- ioctl(sock, SIOCGIFFLAGS, ifr);
- if ((ifr->ifr_flags & IFF_UP) && !(ifr->ifr_flags & IFF_LOOPBACK)) {
- *addr = ia.sin_addr;
- return 0;
+ ret = ioctl(sock, SIOCGIFFLAGS, ifr);
+ if ((ret == 0) && (ifr->ifr_flags & IFF_UP)) {
+ if (env && env_addr.s_addr == ia.sin_addr.s_addr) {
+ *addr = env_addr;
+ return 0;
+ }
+ if (!(ifr->ifr_flags & IFF_LOOPBACK)) {
+ if (!env) {
+ *addr = ia.sin_addr;
+ return 0;
+ }
+ } else {
+ *addr = ia.sin_addr;
+ loopback = true;
+ }
}
}
- return -1;
+ if (env) {
+ ul_logerr("FORB_EXTERNAL_IP doesn't match local interface\n");
+ errno = ENODEV;
+ return -1;
+ }
+ if (loopback)
+ return 0;
+ else
+ return -1;
}
/**
setnonblocking(port_priv->udp_socket);
+#ifndef CONFIG_FORB_PROTO_INET_DEFAULT
struct ip_mreq mreq;
inet_aton(MCAST_ADDR, &port_priv->multicast_addr);
mreq.imr_multiaddr = port_priv->multicast_addr;
IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
if (ret)
goto err_close_udp;
+#endif
addr.sin_family = AF_INET;
addr.sin_port = htons(MCAST_PORT);
}
port_priv->addr.port = addr.sin_port;
- if (listen_on.s_addr == INADDR_ANY)
- get_local_address(port_priv->listen_socket, &port_priv->addr.addr);
- else
+ if (listen_on.s_addr == INADDR_ANY) {
+ if (get_local_address(port_priv->listen_socket, &port_priv->addr.addr)) {
+ goto err_close_listen;
+ }
+ } else
port_priv->addr.addr = listen_on;
/* Initialize epoll descriptor */