|
0
|
1 |
#include "CS.h"
|
|
|
2 |
|
|
|
3 |
CSP csP;
|
|
|
4 |
DebugP deP;
|
|
|
5 |
|
|
|
6 |
void abend(DebugP deP) {
|
|
|
7 |
// LOG(0, "ABORT, netstat:");
|
|
|
8 |
// int pid;
|
|
|
9 |
// if(!(pid = fork())) {
|
|
|
10 |
// execl("/bin/bash", "/bin/bash", "-c", "netstat -n --inet -a | grep 1[123][0-9][0-9][0-9] >net_stat", (char *) NULL);
|
|
|
11 |
// exit(EXIT_SUCCESS);
|
|
|
12 |
// }
|
|
|
13 |
// waitpid(pid, NULL, 0);
|
|
|
14 |
LOG(0, "ABORT, backtrace:");
|
|
|
15 |
back_trace();
|
|
|
16 |
kill(0, SIGTERM);
|
|
|
17 |
exit(EXIT_FAILURE);
|
|
|
18 |
}
|
|
|
19 |
char *gpa(struct sockaddr *ai_addr) { // returns string with IP4 address & port assigned to the socket
|
|
|
20 |
char *s = malloc(64);
|
|
|
21 |
unsigned short port = *(unsigned short*) ai_addr->sa_data;
|
|
|
22 |
char *a = ai_addr->sa_data + 2;
|
|
|
23 |
sprintf(s, "%hhu.%hhu.%hhu.%hhu %hu", a[0], a[1], a[2], a[3], ntohs(port));
|
|
|
24 |
return s;
|
|
|
25 |
}
|
|
|
26 |
void gai(int level, struct addrinfo *ai, DebugP pr) { // logs assigned IP4 addresses from addrinfo chain
|
|
|
27 |
struct addrinfo *sa = ai;
|
|
|
28 |
if (csP->debMaxLev >= level) do {
|
|
|
29 |
char *s = gpa(sa->ai_addr);
|
|
|
30 |
strcpy(pr->msg, s); free(s);
|
|
|
31 |
deb(level, pr);
|
|
|
32 |
} while ((sa = sa->ai_next));
|
|
|
33 |
fflush(stderr);
|
|
|
34 |
}
|
|
|
35 |
void ssl_err(DebugP pr, char *s) {
|
|
|
36 |
long e;
|
|
|
37 |
e = ERR_get_error();
|
|
|
38 |
LOG(4, "ssl err, e=%lu", e);
|
|
|
39 |
while(e) {
|
|
|
40 |
LOG(0, "%s: %s", s, ERR_error_string(e, NULL));
|
|
|
41 |
e = ERR_get_error();
|
|
|
42 |
LOG(4, "ssl err, e=%lu", e);
|
|
|
43 |
}
|
|
|
44 |
abend(pr);
|
|
|
45 |
}
|
|
|
46 |
static int getArg(char *a) {
|
|
|
47 |
return (getenv(a) != NULL) ? atoi(getenv(a)) : 0;
|
|
|
48 |
}
|
|
|
49 |
static void constellation(topology topo, int ssl) {
|
|
|
50 |
DEBID("%sSSL %s", ssl ? "" : "non", topo==mash ? "MASH" : "RING");
|
|
|
51 |
int first, nodes, *forw, pid, stat, exitRc = EXIT_SUCCESS;
|
|
|
52 |
pid_t *pids;
|
|
|
53 |
if(topo==ring) { first=csP->rp0; nodes=csP->rn; }
|
|
|
54 |
if(topo==mash) { first=csP->mp0; nodes=csP->mn; }
|
|
|
55 |
if(nodes == 0) exit(0);
|
|
|
56 |
if(nodes == 1) { LOG(0, "1 node configuration not implemented"); exit(0); }
|
|
|
57 |
LOG(1, "%d node(s) starting...", nodes);
|
|
|
58 |
pids = malloc(nodes*sizeof(int));
|
|
|
59 |
first += ssl*500;
|
|
|
60 |
if((forw = mmap(NULL, sizeof(int), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0)) < 0) SYSERR("mmap");
|
|
|
61 |
*forw = 1;
|
|
|
62 |
for(int i = 0; i < nodes; i++) {
|
|
|
63 |
if(!(pid = fork())) Node(topo, forw, first+i, first, nodes, ssl);
|
|
|
64 |
else { LOG(3, "node %u established in process %u", first+i, pid); pids[i] = (pid_t)pid; }
|
|
|
65 |
}
|
|
|
66 |
LOG(2, "all nodes established");
|
|
|
67 |
while((pid = wait(&stat)) > 0) {
|
|
|
68 |
if(WIFEXITED(stat)) {
|
|
|
69 |
LOG(4, "node process %u ended with exit(%d)", pid, WEXITSTATUS(stat));
|
|
|
70 |
if(WEXITSTATUS(stat) != EXIT_SUCCESS) exitRc = EXIT_FAILURE;
|
|
|
71 |
}
|
|
|
72 |
else { LOG(4, "node process %u crashed", pid); exitRc = EXIT_FAILURE; }
|
|
|
73 |
}
|
|
|
74 |
LOG(1, "ENDED %s", exitRc == EXIT_SUCCESS ? "OK" : "BADLY");
|
|
|
75 |
exit(exitRc);
|
|
|
76 |
}
|
|
|
77 |
int main(int argc, char *argv[]) {
|
|
|
78 |
CST cs;
|
|
|
79 |
csP = &cs;
|
|
|
80 |
deP = &(csP->debug);
|
|
|
81 |
ShareA(csP->shP);
|
|
|
82 |
struct sigaction ign;
|
|
|
83 |
|
|
|
84 |
if(sem_init(&(csP->shP->debugSem), 1, 1) < 0) ERR("LOG sem_init");
|
|
|
85 |
debug_init(argv[0]);
|
|
|
86 |
DEBID("client/server demo");
|
|
|
87 |
if(getArg("DEB") >= 0) csP->debMaxLev = getArg("DEB");
|
|
|
88 |
|
|
|
89 |
if(sem_init(&csP->shP->counterSem, 1, 1) < 0) SYSERR("sem_init");
|
|
|
90 |
ign.sa_flags = 0;
|
|
|
91 |
ign.sa_handler = SIG_IGN;
|
|
|
92 |
if(sigaction(SIGUSR2, &ign, NULL)<0) SYSERR("sigaction");
|
|
|
93 |
|
|
|
94 |
csP->shP->msgs = 0;
|
|
|
95 |
csP->shP->conns = 0;
|
|
|
96 |
csP->text="bla bla";
|
|
|
97 |
csP->ttl = 3;
|
|
|
98 |
csP->rp0 = 11000;
|
|
|
99 |
csP->mp0 = 12000;
|
|
|
100 |
csP->rn = 0;
|
|
|
101 |
csP->mn = 0;
|
|
|
102 |
csP->pace.tv_sec = csP->pace.tv_nsec = 0;
|
|
|
103 |
csP->connThreshold = 77; // connection retries threshold
|
|
|
104 |
csP->connTO = 0.01 * 1000*1000; // connection timeout in usecs
|
|
|
105 |
csP->selTO = 1; // selection timeout in secs
|
|
|
106 |
csP->issl = 0;
|
|
|
107 |
csP->caP = (char*)"/home/local/etc/ssl/certs/";
|
|
|
108 |
char *sslPathSuffP = "/../CS/";
|
|
|
109 |
|
|
|
110 |
if(getenv("T") != NULL) csP->text = getenv("T");
|
|
|
111 |
if(getenv("CEP") != NULL) {
|
|
|
112 |
csP->ceP = (char*)malloc(strlen(getenv("CEP")));
|
|
|
113 |
strcpy(csP->ceP, getenv("CEP")); }
|
|
|
114 |
else {csP->ceP = (char*)malloc(strlen(dirname(argv[0])) + strlen(sslPathSuffP) + 1);
|
|
|
115 |
strcpy(csP->ceP, dirname(argv[0]));
|
|
|
116 |
strcpy(csP->ceP + strlen(dirname(argv[0])), sslPathSuffP); }
|
|
|
117 |
if(getenv("CAP") != NULL) {
|
|
|
118 |
csP->caP = (char*)malloc(strlen(getenv("CAP")) + 1);
|
|
|
119 |
strcpy(csP->caP, getenv("CAP")); }
|
|
|
120 |
if(getArg("TTL") > 0) csP->ttl = getArg("TTL");
|
|
|
121 |
if(getArg("RP0") > 0) csP->rp0 = getArg("RP0");
|
|
|
122 |
if(getArg("MP0") > 0) csP->mp0 = getArg("MP0");
|
|
|
123 |
if(getArg("N") >= 0) {
|
|
|
124 |
csP->mn = getArg("N");
|
|
|
125 |
csP->rn = csP->mn; }
|
|
|
126 |
if(getArg("SSL") >= 0) csP->issl = getArg("SSL");
|
|
|
127 |
if(getArg("RN") >= 0) csP->rn = getArg("RN");
|
|
|
128 |
if(getArg("MN") >= 0) csP->mn = getArg("MN");
|
|
|
129 |
csP->shP->act = csP->rn + csP->mn; // initialize active node processes counter
|
|
|
130 |
if(csP->issl > 1) csP->shP->act += csP->shP->act;
|
|
|
131 |
csP->pacing = 0;
|
|
|
132 |
if(getenv("P") != NULL) {
|
|
|
133 |
double d = atof(getenv("P"));
|
|
|
134 |
csP->pace.tv_sec=(time_t)trunc(d);
|
|
|
135 |
csP->pace.tv_nsec=(d-csP->pace.tv_sec)*1000*1000*1000;
|
|
|
136 |
if(csP->pace.tv_sec > 0 || csP->pace.tv_nsec > 0) csP->pacing = 1;
|
|
|
137 |
}
|
|
|
138 |
if(getArg("RS") >= 0) srandom(getArg("RS"));
|
|
|
139 |
// LOG(5, "initialized: ssl=%u, ssl path: %s, CA path: %s, pace=%f",
|
|
|
140 |
// csP->issl, csP->ceP, csP->caP, (double)csP->pace.tv_sec+(double)csP->pace.tv_nsec/(1000*1000*1000));
|
|
|
141 |
LOG(1, "pgm=%s, ttl=%u, pace=%lu.%03lu, seed=%u, SSL=%u, debug=%d",\
|
|
|
142 |
argv[0], csP->ttl, csP->pace.tv_sec, csP->pace.tv_nsec/(1000*1000), getArg("RS"), csP->issl, csP->debMaxLev);
|
|
|
143 |
if(csP->issl > 0) LOG(3, "certs path=%s, CA certs path=%s", csP->ceP, csP->caP);
|
|
|
144 |
|
|
|
145 |
if(csP->issl < 2) { // 0 = no ssl, 1 = with SSL, 2 = both
|
|
|
146 |
if(!fork()) constellation(ring, csP->issl);
|
|
|
147 |
if(!fork()) constellation(mash, csP->issl);
|
|
|
148 |
} else for(int i = 0; i < 2; i++) {
|
|
|
149 |
if(!fork()) constellation(ring, i);
|
|
|
150 |
if(!fork()) constellation(mash, i);
|
|
|
151 |
}
|
|
|
152 |
|
|
|
153 |
int stat, pid;
|
|
|
154 |
while((pid = wait(&stat)) > 0) if(WIFEXITED(stat)) LOG(4, "constellation process %u ended with exit(%d)", pid, WEXITSTATUS(stat));
|
|
|
155 |
|
|
|
156 |
LOG(1, "final balance: forwards=%d, connections=%d", csP->shP->msgs, csP->shP->conns);
|
|
|
157 |
return 0;
|
|
|
158 |
}
|