+++ /dev/null
-/*
- * $Id$
- *
- * Perform data transfer between our Citadel server and another.
- *
- */
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <string.h>
-#include <errno.h>
-#include <limits.h>
-#include "citadel.h"
-#include "tools.h"
-#include "ipc.h"
-
-/*
- * This variable defines the amount of network spool data that may be carried
- * in one server transfer command. For some reason, some networks get hung
- * up on larger packet sizes. We don't know why. In any case, never set the
- * packet size higher than 4096 or your server sessions will crash.
- */
-#define IGNET_PACKET_SIZE 4000
-
-long atol(const char *);
-
-void serv_read(char *buf, int bytes);
-void serv_write(char *buf, int nbytes);
-void get_config(void);
-struct config config;
-
-
-void logoff(int code)
-{
- exit(code);
-}
-
-
-/*
- * receive network spool from the remote system
- */
-void receive_spool(void)
-{
- long download_len;
- long bytes_received;
- char buf[SIZ];
- static char pbuf[IGNET_PACKET_SIZE];
- char tempfilename[PATH_MAX];
- long plen;
- FILE *fp;
-
- strcpy(tempfilename, tmpnam(NULL));
- serv_puts("NDOP");
- serv_gets(buf);
- printf("%s\n", buf);
- if (buf[0] != '2')
- return;
- download_len = extract_long(&buf[4], 0);
-
- bytes_received = 0L;
- fp = fopen(tempfilename, "w");
- if (fp == NULL) {
- perror("cannot open download file locally");
- return;
- }
- while (bytes_received < download_len) {
- sprintf(buf, "READ %ld|%ld",
- bytes_received,
- ((download_len - bytes_received > IGNET_PACKET_SIZE)
- ? IGNET_PACKET_SIZE : (download_len - bytes_received)));
- serv_puts(buf);
- serv_gets(buf);
- if (buf[0] == '6') {
- plen = extract_long(&buf[4], 0);
- serv_read(pbuf, plen);
- fwrite((char *) pbuf, plen, 1, fp);
- bytes_received = bytes_received + plen;
- }
- }
-
- fclose(fp);
- serv_puts("CLOS");
- serv_gets(buf);
- printf("%s\n", buf);
- sprintf(buf, "mv %s %s/network/spoolin/netpoll.%ld",
- tempfilename, BBSDIR, (long) getpid());
- system(buf);
- system("exec nohup ./netproc >/dev/null 2>&1 &");
-}
-
-/*
- * transmit network spool to the remote system
- */
-void transmit_spool(char *remote_nodename)
-{
- char buf[SIZ];
- char pbuf[4096];
- long plen;
- long bytes_to_write, thisblock;
- int fd;
- char sfname[128];
-
- serv_puts("NUOP");
- serv_gets(buf);
- printf("%s\n", buf);
- if (buf[0] != '2')
- return;
-
- sprintf(sfname, "%s/network/spoolout/%s", BBSDIR, remote_nodename);
- fd = open(sfname, O_RDONLY);
- if (fd < 0) {
- if (errno == ENOENT) {
- printf("Nothing to send.\n");
- } else {
- perror("cannot open upload file locally");
- }
- return;
- }
- while (plen = (long) read(fd, pbuf, IGNET_PACKET_SIZE), plen > 0L) {
- bytes_to_write = plen;
- while (bytes_to_write > 0L) {
- sprintf(buf, "WRIT %ld", bytes_to_write);
- serv_puts(buf);
- serv_gets(buf);
- thisblock = atol(&buf[4]);
- if (buf[0] == '7') {
- serv_write(pbuf, (int) thisblock);
- bytes_to_write = bytes_to_write - thisblock;
- } else {
- goto ABORTUPL;
- }
- }
- }
-
-ABORTUPL:
- close(fd);
- serv_puts("UCLS 1");
- serv_gets(buf);
- printf("%s\n", buf);
- if (buf[0] == '2')
- unlink(sfname);
-}
-
-
-
-
-int main(int argc, char **argv)
-{
- char buf[SIZ];
- char remote_nodename[32];
- int a;
-
- if (argc != 4) {
- fprintf(stderr,
- "%s: usage: %s <address> <port number> <remote netpassword>\n",
- argv[0], argv[0]);
- exit(1);
- }
- get_config();
-
- attach_to_server(argc, argv, NULL, NULL);
- serv_gets(buf);
- printf("%s\n", buf);
- if ((buf[0] != '2') && (strncmp(buf, "551", 3))) {
- fprintf(stderr, "%s: %s\n", argv[0], &buf[4]);
- logoff(atoi(buf));
- }
- serv_puts("INFO");
- serv_gets(buf);
- if (buf[0] == '1') {
- a = 0;
- while (serv_gets(buf), strcmp(buf, "000")) {
- if (a == 1)
- strcpy(remote_nodename, buf);
- if (a == 1)
- printf("Connected to: %s ", buf);
- if (a == 2)
- printf("(%s) ", buf);
- if (a == 6)
- printf("%s\n", buf);
- ++a;
- }
- }
- if (!strcmp(remote_nodename, config.c_nodename)) {
- fprintf(stderr, "Connected to local system\n");
- } else {
- sprintf(buf, "NETP %s|%s", config.c_nodename, argv[3]);
- serv_puts(buf);
- serv_gets(buf);
- printf("%s\n", buf);
-
- /* only do the transfers if we authenticated correctly! */
- if (buf[0] == '2') {
- receive_spool();
- transmit_spool(remote_nodename);
- }
- }
-
- serv_puts("QUIT");
- serv_gets(buf);
- exit(0);
-}
*
*/
+/*
+ * FIXME do something about concurrency issues:
+ * 1. Don't allow the two nodes to poll each other at the same time
+ * 2. Don't allow polls during network processing
+ * 3. Kill Bill Gates using either a chainsaw or a wood chipper
+ */
+
#include "sysdep.h"
#include <stdlib.h>
#include <unistd.h>
#include "tools.h"
#include "internet_addressing.h"
#include "serv_network.h"
+#include "clientsocket.h"
/*
}
+
+
+
+/*
+ * receive network spool from the remote system
+ */
+void receive_spool(int sock, char *remote_nodename) {
+ long download_len;
+ long bytes_received;
+ char buf[SIZ];
+ static char pbuf[IGNET_PACKET_SIZE];
+ char tempfilename[PATH_MAX];
+ long plen;
+ FILE *fp;
+
+ strcpy(tempfilename, tmpnam(NULL));
+ if (sock_puts(sock, "NDOP") < 0) return;
+ if (sock_gets(sock, buf) < 0) return;
+ lprintf(9, "<%s\n", buf);
+ if (buf[0] != '2') {
+ return;
+ }
+ download_len = extract_long(&buf[4], 0);
+
+ bytes_received = 0L;
+ fp = fopen(tempfilename, "w");
+ if (fp == NULL) {
+ lprintf(9, "cannot open download file locally: %s\n",
+ strerror(errno));
+ return;
+ }
+
+ while (bytes_received < download_len) {
+ sprintf(buf, "READ %ld|%ld",
+ bytes_received,
+ ((download_len - bytes_received > IGNET_PACKET_SIZE)
+ ? IGNET_PACKET_SIZE : (download_len - bytes_received)));
+ if (sock_puts(sock, buf) < 0) {
+ fclose(fp);
+ unlink(tempfilename);
+ return;
+ }
+ if (sock_gets(sock, buf) < 0) {
+ fclose(fp);
+ unlink(tempfilename);
+ return;
+ }
+ if (buf[0] == '6') {
+ plen = extract_long(&buf[4], 0);
+ if (sock_read(sock, pbuf, plen) < 0) {
+ fclose(fp);
+ unlink(tempfilename);
+ return;
+ }
+ fwrite((char *) pbuf, plen, 1, fp);
+ bytes_received = bytes_received + plen;
+ }
+ }
+
+ fclose(fp);
+ if (sock_puts(sock, "CLOS") < 0) {
+ unlink(tempfilename);
+ return;
+ }
+ if (sock_gets(sock, buf) < 0) {
+ unlink(tempfilename);
+ return;
+ }
+ lprintf(9, "%s\n", buf);
+ sprintf(buf, "mv %s ./network/spoolin/%s.%ld",
+ tempfilename, remote_nodename, (long) getpid());
+ system(buf);
+}
+
+
+
+/*
+ * transmit network spool to the remote system
+ */
+void transmit_spool(int sock, char *remote_nodename)
+{
+ char buf[SIZ];
+ char pbuf[4096];
+ long plen;
+ long bytes_to_write, thisblock;
+ int fd;
+ char sfname[128];
+
+ if (sock_puts(sock, "NUOP") < 0) return;
+ if (sock_gets(sock, buf) < 0) return;
+ lprintf(9, "<%s\n", buf);
+ if (buf[0] != '2') {
+ return;
+ }
+
+ sprintf(sfname, "./network/spoolout/%s", remote_nodename);
+ fd = open(sfname, O_RDONLY);
+ if (fd < 0) {
+ if (errno == ENOENT) {
+ lprintf(9, "Nothing to send.\n");
+ } else {
+ lprintf(5, "cannot open upload file locally: %s\n",
+ strerror(errno));
+ }
+ return;
+ }
+ while (plen = (long) read(fd, pbuf, IGNET_PACKET_SIZE), plen > 0L) {
+ bytes_to_write = plen;
+ while (bytes_to_write > 0L) {
+ sprintf(buf, "WRIT %ld", bytes_to_write);
+ if (sock_puts(sock, buf) < 0) {
+ close(fd);
+ return;
+ }
+ if (sock_gets(sock, buf) < 0) {
+ close(fd);
+ return;
+ }
+ thisblock = atol(&buf[4]);
+ if (buf[0] == '7') {
+ if (sock_write(sock, pbuf,
+ (int) thisblock) < 0) {
+ close(fd);
+ return;
+ }
+ bytes_to_write = bytes_to_write - thisblock;
+ } else {
+ goto ABORTUPL;
+ }
+ }
+ }
+
+ABORTUPL:
+ close(fd);
+ if (sock_puts(sock, "UCLS 1") < 0) return;
+ if (sock_gets(sock, buf) < 0) return;
+ lprintf(9, "<%s\n", buf);
+ if (buf[0] == '2') {
+ unlink(sfname);
+ }
+}
+
+
+
+/*
+ * Poll one Citadel node (called by network_poll_other_citadel_nodes() below)
+ */
+void network_poll_node(char *node, char *secret, char *host, char *port) {
+ int sock;
+ char buf[SIZ];
+
+ lprintf(5, "Polling node <%s> at %s:%s\n", node, host, port);
+
+ sock = sock_connect(host, port, "tcp");
+ if (sock < 0) {
+ lprintf(7, "Could not connect: %s\n", strerror(errno));
+ return;
+ }
+
+ lprintf(9, "Connected!\n");
+
+ /* Read the server greeting */
+ if (sock_gets(sock, buf) < 0) goto bail;
+ lprintf(9, ">%s\n", buf);
+
+ /* Identify ourselves */
+ sprintf(buf, "NETP %s|%s", config.c_nodename, secret);
+ lprintf(9, "<%s\n", buf);
+ if (sock_puts(sock, buf) <0) goto bail;
+ if (sock_gets(sock, buf) < 0) goto bail;
+ lprintf(9, ">%s\n", buf);
+ if (buf[0] != '2') goto bail;
+
+ /* At this point we are authenticated. */
+ receive_spool(sock, node);
+ transmit_spool(sock, node);
+
+ sock_puts(sock, "QUIT");
+bail: sock_close(sock);
+}
+
+
+
+/*
+ * Poll other Citadel nodes and transfer inbound/outbound network data.
+ */
+void network_poll_other_citadel_nodes(void) {
+ char *ignetcfg = NULL;
+ int i;
+ char linebuf[SIZ];
+ char node[SIZ];
+ char host[SIZ];
+ char port[SIZ];
+ char secret[SIZ];
+
+ ignetcfg = CtdlGetSysConfig(IGNETCFG);
+ if (ignetcfg == NULL) return; /* no nodes defined */
+
+ /* Use the string tokenizer to grab one line at a time */
+ for (i=0; i<num_tokens(ignetcfg, '\n'); ++i) {
+ extract_token(linebuf, ignetcfg, i, '\n');
+ extract(node, linebuf, 0);
+ extract(secret, linebuf, 1);
+ extract(host, linebuf, 2);
+ extract(port, linebuf, 3);
+ if ( (strlen(node) > 0) && (strlen(secret) > 0)
+ && (strlen(host) > 0) && strlen(port) > 0) {
+ network_poll_node(node, secret, host, port);
+ }
+ }
+
+ phree(ignetcfg);
+}
+
+
+
+
+
+
+
/*
* network_do_queue()
*
doing_queue = 1;
last_run = time(NULL);
+ /*
+ * Poll other Citadel nodes.
+ */
+ network_poll_other_citadel_nodes();
+
+ /*
+ * Load the network map into memory.
+ */
read_network_map();
/*