#include <glib/galloca.h>
#include <glib/gprintf.h>
#include <glib/grand.h>
+#include <glib/gutils.h>
#include "network.h"
#include "packet.h"
#include "main.h" /* for optarg_verbose */
+#include "pathname.h"
/* Config: */
-#define NETWORK_PATHNAME_PID "/var/run/udpgate.pid"
-#define SOCK_SOURCE_CHECK_EVENTS (G_IO_IN) /* |G_IO_PRI */
-#define SOCK_SOURCE_CHECK_REVENTS (SOCK_SOURCE_CHECK_EVENTS) /* |G_IO_ERR|G_IO_HUP|G_IO_NVAL */
-#define SERVER_INADDR 0x511F02EA /* paulina.vellum.cz = 81.31.2.234; host order */
+#define SOCK_SOURCE_CHECK_REVENTS (G_IO_IN|G_IO_OUT) /* |G_IO_ERR|G_IO_HUP|G_IO_NVAL */
+#define SERVER_INADDR 0xC37AD054 /* mms2.org = 195.122.208.84; host order */
#define SERVER_PORT 9201 /* host order */
#define PROBE_INADDR SERVER_INADDR /* host order */
#define PROBE_PORT 8201 /* host order */
#define CLIENT_TIMEOUT_SEC (5*60)
#define PROBE_TIMEOUT_SEC_BASE 5
#define PROBE_TIMEOUT_SEC_MAX 3500
+#define TCP_BACKLOG 5
+#define GSTRING_TO_SEND_MAX 1500*6 /* maximum data buffered per TCP client */
void (*network_notify_hostip)(guint32 hostip_guint32);
+static G_CONST_RETURN gchar *pid_pathname(void)
+{
+static const gchar *static_pathname;
+static const char *user_val;
+
+ if (!static_pathname)
+ user_val=g_get_user_name();
+ return pathname_find(&static_pathname,
+ G_STRINGIFY(LOCALSTATEDIR) "/run",PACKAGE ".pid",
+ (!user_val ? NULL : g_get_tmp_dir()),
+ (!user_val ? NULL : udpgate_printf_alloca(".%s-%s.pid",user_val,PACKAGE)),
+ NULL);
+}
+
+
struct client {
GPollFD gpollfd;
struct sockaddr_in sockaddr_in_from;
guint timeout_id;
+ struct client *bound;
+ unsigned connect_pending:1; /* for TCP connection to the server; activated by: G_IO_OUT */
+ unsigned server_only:1; /* nonimportant connect - the server side */
+ unsigned done:1; /* temporary marker */
+ GString *gstring_to_send; /* for TCP connections; data to be sent to this socket */
};
static GSource *sock_gsource;
static GList *sock_client_list; /* of 'struct client *', incl. 'master' and 'probe' */
-static struct client *master; /* no 'timeout' permitted */
+static struct client *master_udp; /* no 'timeout' permitted */
+static struct client *master_tcp; /* no 'timeout' permitted */
static struct client *probe; /* 'timeout' permitted */
static guint32 probe_unique;
static guint probe_timeout_sec_now;
if (sock_gsource)
return getpid();
- if (!(f=fopen(NETWORK_PATHNAME_PID,"r")))
+ if (!(f=fopen(pid_pathname(),"r")))
goto err;
got=fgets(buf,sizeof(buf),f);
fclose(f); /* FIXME: error ignored */
FILE *f;
if (pid==(pid_t)-1) {
- if (unlink(NETWORK_PATHNAME_PID)) {
+ if (unlink(pid_pathname())) {
if (errno!=ENOENT)
- g_warning(_("Error removing PID file \"%s\": %m"),NETWORK_PATHNAME_PID);
+ g_warning(_("Error removing PID file \"%s\": %m"),pid_pathname());
return FALSE;
}
return TRUE;
}
- if (!(f=fopen(NETWORK_PATHNAME_PID,"w"))) {
- g_warning(_("Error writing PID %d to \"%s\": %m"),(int)pid,NETWORK_PATHNAME_PID);
+ if (!(f=fopen(pid_pathname(),"w"))) {
+static gboolean once=TRUE;
+
+ if (once) {
+ once=FALSE;
+ g_warning(_("Error writing PID %d to \"%s\": %m"),(int)pid,pid_pathname());
+ }
return FALSE;
}
fprintf(f,"%d\n",(int)pid); /* errors ignored */
static void client_timeout_remove(struct client *client)
{
g_return_if_fail(client!=NULL);
- g_return_if_fail(client!=master);
+ g_return_if_fail(client!=master_udp);
+ g_return_if_fail(client!=master_tcp);
if (client->timeout_id) {
gboolean errgboolean;
static void client_touch(struct client *client,guint timeout_sec)
{
g_return_if_fail(client!=NULL);
- g_return_if_fail(client!=master);
+ g_return_if_fail(client!=master_udp);
+ g_return_if_fail(client!=master_tcp);
g_return_if_fail(timeout_sec>0);
client_timeout_remove(client);
static gboolean client_touch_timeout(struct client *client)
{
g_return_val_if_fail(client!=NULL,FALSE); /* FALSE=>should be removed */
- g_return_val_if_fail(client!=master,FALSE); /* FALSE=>should be removed */
+ g_return_val_if_fail(client!=master_udp,FALSE); /* FALSE=>should be removed */
+ g_return_val_if_fail(client!=master_tcp,FALSE); /* FALSE=>should be removed */
if (optarg_verbose)
g_message(_("Client fd %d timeout id %d occured/entered"),client->gpollfd.fd,client->timeout_id);
(*network_notify_hostip)(hostip_guint32);
}
-static struct client *client_new(void);
+enum client_new_type {
+ CLIENT_NEW_TYPE_UDP,
+ CLIENT_NEW_TYPE_TCP,
+ };
+
+static struct client *client_new(enum client_new_type type);
+static struct client *client_new_from_sock(int sock);
-static void handle_master(struct client *master)
+static void clients_bind(struct client *client0,struct client *client1)
{
- g_return_if_fail(master!=NULL);
+ g_return_if_fail(client0!=NULL);
+ g_return_if_fail(client0->bound==NULL);
+ g_return_if_fail(client0->gstring_to_send==NULL);
+ g_return_if_fail(client1!=NULL);
+ g_return_if_fail(client1->bound==NULL);
+ g_return_if_fail(client1->gstring_to_send==NULL);
+ g_return_if_fail(client0!=client1);
+
+ client0->bound=client1;
+ client1->bound=client0;
+
+ client0->gstring_to_send=g_string_sized_new(GSTRING_TO_SEND_MAX);
+ client1->gstring_to_send=g_string_sized_new(GSTRING_TO_SEND_MAX);
+}
+
+static void client_split(struct client *client)
+{
+ g_return_if_fail(client!=NULL);
+ g_return_if_fail(client->bound!=NULL);
+ g_return_if_fail(client->bound!=client);
+ g_return_if_fail(client->bound->bound==client);
+ g_return_if_fail(client->gstring_to_send!=NULL);
+
+ client->bound->bound=NULL;
+ client->bound=NULL;
+}
+
+static struct sockaddr_in sockaddr_in_server;
+
+static void handle_master_udp(struct client *master_udp)
+{
+ g_return_if_fail(master_udp!=NULL);
for (;;) {
char packet[0x10000];
ssize_t gotlen;
struct sockaddr_in sockaddr_in_from;
struct client *client=NULL /* Prevent false positive: might be used uninitialized */;
-struct sockaddr_in sockaddr_in_server;
socklen_t sockaddr_in_from_length;
GList *clientl;
sockaddr_in_from_length=sizeof(sockaddr_in_from);
if (-1==(gotlen=recvfrom(
- master->gpollfd.fd, /* s */
+ master_udp->gpollfd.fd, /* s */
packet, /* buf */
sizeof(packet), /* len */
0, /* flags */
/* FIXME: Performance: Ugly search... */
for (clientl=sock_client_list;clientl;clientl=clientl->next) {
client=clientl->data;
- if (client==master)
+ if (client==master_udp)
continue;
if (1
&& client->sockaddr_in_from.sin_family ==sockaddr_in_from.sin_family
break;
}
if (!clientl) {
- client=client_new();
+ client=client_new(CLIENT_NEW_TYPE_UDP);
client->sockaddr_in_from=sockaddr_in_from;
}
client_touch(client,CLIENT_TIMEOUT_SEC);
- UDPGATE_MEMZERO(&sockaddr_in_server);
- sockaddr_in_server.sin_family=AF_INET;
- sockaddr_in_server.sin_port=htons(SERVER_PORT);
- sockaddr_in_server.sin_addr.s_addr=htonl(SERVER_INADDR);
/* FIXME: errors checking */
sendto(
client->gpollfd.fd, /* s */
}
}
+static void handle_master_tcp(struct client *master_tcp)
+{
+ g_return_if_fail(master_tcp!=NULL);
+
+ for (;;) {
+int sock_new;
+struct sockaddr_in sockaddr_in_from;
+struct client *client=NULL /* Prevent false positive: might be used uninitialized */;
+socklen_t sockaddr_in_from_length;
+int connect_got;
+struct client *server;
+
+ sockaddr_in_from_length=sizeof(sockaddr_in_from);
+ if (-1==(sock_new=accept(
+ master_tcp->gpollfd.fd, /* s */
+ (struct sockaddr *)&sockaddr_in_from, /* from */
+ &sockaddr_in_from_length))) /* fromlen */
+ break;
+
+ if (sockaddr_in_from_length!=sizeof(sockaddr_in_from)) /* FIXME: errors reporting */
+ continue;
+
+ /* Not yet initialized by 'probe' reply - drop it. */
+ if (probe) {
+ if (optarg_verbose)
+ g_message(_("Incoming connection received from %s but no probe reply yet; dropping connection."),
+ SOCKADDR_IN_TO_STRING(&sockaddr_in_from));
+ close(sock_new); /* FIXME: errors reporting */
+ continue;
+ }
+
+ if (!(client=client_new_from_sock(sock_new)))
+ continue;
+ client->sockaddr_in_from=sockaddr_in_from;
+
+ if (!(server=client_new(CLIENT_NEW_TYPE_TCP))) {
+ client_destroy(client);
+ continue;
+ }
+ server->server_only=1;
+ server->sockaddr_in_from=sockaddr_in_server;
+ clients_bind(client,server);
+ /* Currently only one of 'client' or 'server' needs to be destroyed. */
+
+ errno=0;
+ connect_got=connect(
+ server->gpollfd.fd, /* sockfd */
+ (struct sockaddr *)&sockaddr_in_server, /* to */
+ sizeof(sockaddr_in_server)); /* tolen */
+ if (connect_got!=-1 || errno!=EINPROGRESS) {
+ g_warning(_("Error establishing server TCP connection: %m"));
+ client_destroy(server);
+ continue;
+ }
+ g_assert(!server->connect_pending);
+ server->connect_pending=1;
+ }
+}
+
static void handle_probe(struct client *probe)
{
g_return_if_fail(probe!=NULL);
sockaddr_in_from_length=sizeof(sockaddr_in_from);
if (-1==(gotlen=recvfrom(
- master->gpollfd.fd, /* s */
+ master_udp->gpollfd.fd, /* s */
packet, /* buf */
sizeof(packet), /* len */
0, /* flags */
}
}
-static void handle_client(struct client *client)
+static void handle_client_udp(struct client *client)
{
g_return_if_fail(client!=NULL);
- g_return_if_fail(master!=NULL);
+ g_return_if_fail(master_udp!=NULL);
for (;;) {
ssize_t gotlen;
struct sockaddr_in sockaddr_in_from;
-char packet [0x10000];
+char packet[0x10000];
socklen_t sockaddr_in_from_length;
sockaddr_in_from_length=sizeof(sockaddr_in_from);
client_touch(client,CLIENT_TIMEOUT_SEC);
/* FIXME: errors checking */
sendto(
- master->gpollfd.fd, /* s */
+ master_udp->gpollfd.fd, /* s */
packet, /* msg */
gotlen, /* len */
0, /* flags */
}
}
+static void handle_client_tcp_connect(struct client *server)
+{
+ g_return_if_fail(server!=NULL);
+ g_return_if_fail(server->connect_pending);
+ g_return_if_fail(master_tcp!=NULL);
+
+ errno=0;
+ if (connect(
+ server->gpollfd.fd, /* sockfd */
+ (struct sockaddr *)&sockaddr_in_server, /* to */
+ sizeof(sockaddr_in_server))) { /* tolen */
+ g_warning(_("Error establishing server TCP connection: %m"));
+ client_destroy(server);
+ return;
+ }
+ g_assert(server->connect_pending);
+ server->connect_pending=0;
+}
+
+/* Read from client->gpollfd.fd the data for client->bound->gstring_to_send. */
+static void handle_client_tcp_read(struct client *client)
+{
+ g_return_if_fail(client!=NULL);
+ g_return_if_fail(client->bound!=NULL);
+ g_return_if_fail(!client->connect_pending);
+ g_return_if_fail(master_tcp!=NULL);
+
+ for (;;) {
+ssize_t gotlen;
+size_t read_max;
+char buf[GSTRING_TO_SEND_MAX];
+
+ read_max=sizeof(buf)-client->bound->gstring_to_send->len;
+ g_assert(read_max>=0);
+ if (read_max<=0) /* In fact it initially should not happen, there would be no: G_IO_IN */
+ break;
+ gotlen=read(client->gpollfd.fd,buf,read_max);
+ if (gotlen==-1) {
+ if (errno==EAGAIN)
+ break;
+ g_warning(_("Error reading data from %s"),SOCKADDR_IN_TO_STRING(&client->sockaddr_in_from));
+ client_destroy(client);
+ return;
+ }
+ if (gotlen==0) {
+ /* Successful close; leave the bound peer's 'gstring_to_send' to be written there. */
+ if (client->server_only && client->bound->gstring_to_send->len)
+ client_split(client);
+ client_destroy(client);
+ return;
+ }
+ g_assert(gotlen>0);
+ g_assert((size_t)gotlen<=read_max);
+ g_string_append_len(client->bound->gstring_to_send,buf,gotlen);
+ }
+}
+
+/* Write to client->gpollfd.fd the data from client->gstring_to_send. */
+static void handle_client_tcp_write(struct client *client)
+{
+ g_return_if_fail(client!=NULL);
+ g_return_if_fail(!client->connect_pending);
+ g_return_if_fail(master_tcp!=NULL);
+
+ for (;;) {
+ssize_t gotlen;
+
+ if (client->gstring_to_send->len<=0) /* In fact it initially should not happen, there would be no: G_IO_OUT */
+ break;
+ gotlen=write(client->gpollfd.fd,client->gstring_to_send->str,client->gstring_to_send->len);
+ if (gotlen==-1) {
+ if (errno==EAGAIN)
+ break;
+ g_warning(_("Error writing data to %s"),SOCKADDR_IN_TO_STRING(&client->sockaddr_in_from));
+ client_destroy(client);
+ return;
+ }
+ if (gotlen<=0)
+ break;
+ g_assert((size_t)gotlen<=client->gstring_to_send->len);
+ g_string_erase(client->gstring_to_send,0,gotlen);
+ }
+
+ /* Nothing left to do for such client. */
+ if (!client->gstring_to_send->len && !client->bound)
+ client_destroy(client);
+}
+
static gboolean sock_source_callback(gpointer data /* unused */)
{
GList *clientl;
+ /* FIXME: Quadratic 'done' marking to not to stick on stale entry! */
+
for (clientl=sock_client_list;clientl;clientl=clientl->next) {
struct client *client=clientl->data;
- if (client->gpollfd.revents&SOCK_SOURCE_CHECK_REVENTS) {
- /**/ if (client==master)
- handle_master(client);
+ client->done=0;
+ }
+retry_in:
+ for (clientl=sock_client_list;clientl;clientl=clientl->next) {
+struct client *client=clientl->data;
+
+ if (client->done)
+ continue;
+ client->done=1;
+ if (client->gpollfd.revents&G_IO_IN) {
+ /**/ if (client==master_udp)
+ handle_master_udp(client);
+ else if (client==master_tcp)
+ handle_master_tcp(client);
else if (client==probe)
handle_probe(client);
+ else if (client->connect_pending)
+ g_assert_not_reached();
+ else if (client->bound)
+ handle_client_tcp_read(client);
else
- handle_client(client);
+ handle_client_udp(client);
}
+ goto retry_in;
+ }
+
+ for (clientl=sock_client_list;clientl;clientl=clientl->next) {
+struct client *client=clientl->data;
+
+ client->done=0;
+ }
+retry_out:
+ for (clientl=sock_client_list;clientl;clientl=clientl->next) {
+struct client *client=clientl->data;
+
+ if (client->done)
+ continue;
+ client->done=1;
+ if (client->gpollfd.revents&G_IO_OUT) {
+ /**/ if (client==master_udp)
+ g_assert_not_reached();
+ else if (client==master_tcp)
+ g_assert_not_reached();
+ else if (client==probe)
+ g_assert_not_reached();
+ else if (client->connect_pending)
+ handle_client_tcp_connect(client);
+ else if (client->gstring_to_send)
+ handle_client_tcp_write(client);
+ else
+ g_assert_not_reached();
+ }
+ goto retry_out;
}
return TRUE; /* the source should be kept active */
static gboolean sock_source_prepare(GSource *source,gint *timeout)
{
+GList *clientl;
+
*timeout=-1;
+ for (clientl=sock_client_list;clientl;clientl=clientl->next) {
+struct client *client=clientl->data;
+
+ client->gpollfd.events=G_IO_IN;
+ if (!client->bound && client->gstring_to_send)
+ client->gpollfd.events&=~G_IO_IN;
+ if (client->bound && client->bound->gstring_to_send->len>=GSTRING_TO_SEND_MAX)
+ client->gpollfd.events&=~G_IO_IN;
+ if (client->connect_pending)
+ client->gpollfd.events&=~G_IO_IN;
+ if (client->bound && client->bound->connect_pending)
+ client->gpollfd.events&=~G_IO_IN;
+ if (client->connect_pending)
+ client->gpollfd.events|=G_IO_OUT;
+ if (client->gstring_to_send && client->gstring_to_send->len>0)
+ client->gpollfd.events|=G_IO_OUT;
+ g_assert(!(client->gpollfd.events&~SOCK_SOURCE_CHECK_REVENTS));
+ }
return FALSE;
}
while (sock_client_list)
client_destroy(sock_client_list->data);
- g_assert(master==NULL);
+ g_assert(master_udp==NULL);
+ g_assert(master_tcp==NULL);
g_assert(probe==NULL);
if (sock_gsource) {
return TRUE;
}
-static struct client *client_new(void)
+static struct client *client_new_from_sock(int sock)
{
struct client *client;
static unsigned long oneul=1;
-int sock;
+
+ g_return_val_if_fail(sock>=0,NULL);
if (!sock_gsource_new())
return FALSE;
- if (-1==(sock=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))) {
- g_warning("socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP): %m");
- return NULL;
- }
if (ioctl(sock,FIONBIO,&oneul)) { /* non-blocking mode */
g_warning("ioctl(sock,FIONBIO,&1): %m");
close(sock); /* errors ignored */
udpgate_new(client);
client->gpollfd.fd=sock;
- client->gpollfd.events=SOCK_SOURCE_CHECK_EVENTS;
- client->gpollfd.revents=0;
+ client->gpollfd.events=0; /* Initialized later. */
+ client->gpollfd.revents=0; /* Probably does not need to be initialized. */
client->timeout_id=0;
+ client->bound=NULL;
+ client->connect_pending=0;
+ client->server_only=0;
+ client->gstring_to_send=0;
sock_client_list=g_list_prepend(sock_client_list,client);
g_source_add_poll(sock_gsource,&client->gpollfd);
return client;
}
+static struct client *client_new(enum client_new_type type)
+{
+int sock;
+
+ switch (type) {
+ case CLIENT_NEW_TYPE_UDP:
+ if (-1==(sock=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP))) {
+ g_warning("socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP): %m");
+ return NULL;
+ }
+ break;
+ case CLIENT_NEW_TYPE_TCP:
+ if (-1==(sock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))) {
+ g_warning("socket(PF_INET,SOCK_STREAM,IPPROTO_TCP): %m");
+ return NULL;
+ }
+ break;
+ default: g_assert_not_reached();
+ }
+
+ return client_new_from_sock(sock);
+}
+
static void client_destroy(struct client *client)
{
+struct client *bound;
+
g_return_if_fail(client!=NULL);
if (!sock_gsource_new())
if (optarg_verbose)
g_message(_("Client fd %d timeout id %d destroy enter"),client->gpollfd.fd,client->timeout_id);
- if (client==master) {
- master=NULL;
+ if (client==master_udp) {
+ master_udp=NULL;
+ g_assert(client->timeout_id==0);
+ }
+ else if (client==master_tcp) {
+ master_tcp=NULL;
g_assert(client->timeout_id==0);
}
else {
sock_client_list=g_list_remove(sock_client_list,client);
close(client->gpollfd.fd); /* errors ignored */
+ if (client->gstring_to_send)
+ g_string_free(client->gstring_to_send,TRUE);
+
if (optarg_verbose)
g_message(_("Client fd %d timeout id %d destroy finish"),client->gpollfd.fd,client->timeout_id);
+ bound=client->bound;
g_free(client);
+
+ if (bound) {
+ g_assert(bound!=client);
+ g_assert(bound->bound==client);
+ client->bound=NULL;
+ bound->bound=NULL;
+ client_destroy(bound);
+ }
}
static gboolean probe_send(struct client *probe,gint port_local)
{
-struct sockaddr_in sockaddr_in_server;
+struct sockaddr_in sockaddr_in_probe;
GHashTable *probe_hash;
gpointer packet;
size_t packet_length;
if (!packet)
return FALSE;
- UDPGATE_MEMZERO(&sockaddr_in_server);
- sockaddr_in_server.sin_family=AF_INET;
- sockaddr_in_server.sin_port=htons(PROBE_PORT);
- sockaddr_in_server.sin_addr.s_addr=htonl(PROBE_INADDR);
+ UDPGATE_MEMZERO(&sockaddr_in_probe);
+ sockaddr_in_probe.sin_family=AF_INET;
+ sockaddr_in_probe.sin_port=htons(PROBE_PORT);
+ sockaddr_in_probe.sin_addr.s_addr=htonl(PROBE_INADDR);
/* FIXME: errors checking */
sendto(
probe->gpollfd.fd, /* s */
packet, /* msg */
packet_length, /* len */
0, /* flags */
- (struct sockaddr *)&sockaddr_in_server, /* to */
- sizeof(sockaddr_in_server)); /* tolen */
+ (struct sockaddr *)&sockaddr_in_probe, /* to */
+ sizeof(sockaddr_in_probe)); /* tolen */
+
+ return TRUE;
+}
+
+static gboolean master_udp_start(gint port,const struct sockaddr_in *sockaddr_in_pointer)
+{
+ g_return_val_if_fail(master_udp==NULL,FALSE);
+
+ if (!(master_udp=client_new(CLIENT_NEW_TYPE_UDP)))
+ return FALSE;
+ if (bind(master_udp->gpollfd.fd,(struct sockaddr *)sockaddr_in_pointer,sizeof(*sockaddr_in_pointer))) {
+ g_warning("bind(sock_udp,{AF_INET,INADDR_ANY:%d}): %m",(int)port);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean master_tcp_start(gint port,const struct sockaddr_in *sockaddr_in_pointer)
+{
+static int onei=1;
+
+ g_return_val_if_fail(master_tcp==NULL,FALSE);
+ if (!(master_tcp=client_new(CLIENT_NEW_TYPE_TCP)))
+ return FALSE;
+ if (setsockopt(master_tcp->gpollfd.fd,SOL_SOCKET,SO_REUSEADDR,&onei,sizeof(onei))) {
+ g_warning("setsockopt(sock_tcp,SOL_SOCKET,SO_REUSEADDR,1): %m");
+ return FALSE;
+ }
+ if (bind(master_tcp->gpollfd.fd,(struct sockaddr *)sockaddr_in_pointer,sizeof(*sockaddr_in_pointer))) {
+ g_warning("bind(sock_tcp,{AF_INET,INADDR_ANY:%d}): %m",(int)port);
+ return FALSE;
+ }
+ if (listen(master_tcp->gpollfd.fd,TCP_BACKLOG)) {
+ g_warning("listen(sock_tcp,%d): %m",TCP_BACKLOG);
+ return FALSE;
+ }
return TRUE;
}
static gboolean master_start(gint port)
{
struct sockaddr_in sockaddr_in;
+uint16_t port_use;
g_return_val_if_fail(port>=0,FALSE);
- g_return_val_if_fail(master==NULL,FALSE);
+ g_return_val_if_fail(master_udp==NULL,FALSE);
+ g_return_val_if_fail(master_tcp==NULL,FALSE);
- /* Setup 'master': */
- if (!(master=client_new()))
+ port_use=port;
+ if (port < 0 || port_use != port) {
+ g_warning(_("Port value %d is not valid for IPv4!"),(int)port);
return FALSE;
+ }
UDPGATE_MEMZERO(&sockaddr_in);
sockaddr_in.sin_family=AF_INET;
- sockaddr_in.sin_port=htons(port);
+ sockaddr_in.sin_port=htons(port_use);
sockaddr_in.sin_addr.s_addr=htonl(INADDR_ANY);
- if (bind(master->gpollfd.fd,(struct sockaddr *)&sockaddr_in,sizeof(sockaddr_in))) {
- g_warning("bind(sock,{AF_INET,INADDR_ANY:%d}): %m",(int)port);
+
+ if (!master_udp_start(port,&sockaddr_in))
+ return FALSE;
+ if (!master_tcp_start(port,&sockaddr_in)) {
+ client_destroy(master_udp);
return FALSE;
}
return TRUE;
g_return_val_if_fail(probe==NULL,FALSE);
/* Setup 'probe': */
- if (!(probe=client_new()))
+ if (!(probe=client_new(CLIENT_NEW_TYPE_UDP)))
return FALSE;
port_local=port;
if (!probe_send(probe,port)) {
g_return_val_if_fail(port>=0,FALSE);
+ UDPGATE_MEMZERO(&sockaddr_in_server);
+ sockaddr_in_server.sin_family=AF_INET;
+ sockaddr_in_server.sin_port=htons(SERVER_PORT);
+ sockaddr_in_server.sin_addr.s_addr=htonl(SERVER_INADDR);
+
if ((pid_t)-1!=(daemon_pid=is_daemon_running())) {
g_warning(_("Cannot start network daemon: Daemon is already running on PID %d"),(int)daemon_pid);
return FALSE;