summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorGravatar Karl Ramm <kcr@1ts.org>2013-03-16 23:03:09 -0700
committerGravatar Karl Ramm <kcr@1ts.org>2013-03-16 23:58:03 -0700
commita48880c2b45e31ace09e037b1567f98f7ba4be9f (patch)
tree3370f7eb2e985f6c37df8eaec3ecd47d8b6d97c9 /server
parent9e8331c95c94003458ec0a9f9a750bee9f25fdbd (diff)
rototill uloc.c to be a little less pathological
Notably, use realloc rather than allocating and copying a whole new table. Also be more consistent about operating in terms of array indices rather then pointers.
Diffstat (limited to 'server')
-rw-r--r--server/test_server.c47
-rw-r--r--server/uloc.c330
2 files changed, 124 insertions, 253 deletions
diff --git a/server/test_server.c b/server/test_server.c
index e9ff71e..f613b6f 100644
--- a/server/test_server.c
+++ b/server/test_server.c
@@ -18,10 +18,11 @@ int ulogin_add_user(ZNotice_t *notice, Exposure_type exposure,
Exposure_type ulogin_remove_user(ZNotice_t *notice,
struct sockaddr_in *who,
int *err_return);
-Location *ulogin_find(char *user, struct in_addr *host,
+int ulogin_find(char *user, struct in_addr *host,
unsigned int port);
-Location *ulogin_find_user(char *user);
+int ulogin_find_user(char *user);
void ulogin_flush_user(ZNotice_t *notice);
+extern Location *locations;
#define TEST(EXP) \
do { \
@@ -66,7 +67,7 @@ test_uloc() {
puts("uloc storage routines");
- TEST(ulogin_find_user("nonexistent") == NULL);
+ TEST(ulogin_find_user("nonexistent") == -1);
/* fake up just enough */
who1.sin_family = AF_INET;
@@ -81,7 +82,7 @@ test_uloc() {
s1 = make_string(z1.z_class_inst, 0);
TEST(ulogin_add_user(&z1, NET_ANN, &who1) == 0);
- TEST(ulogin_find_user("user1") != NULL);
+ TEST(ulogin_find_user("user1") != -1);
who2.sin_family = AF_INET;
who2.sin_port = 2;
@@ -95,18 +96,18 @@ test_uloc() {
s2 = make_string(z2.z_class_inst, 0);
TEST(ulogin_add_user(&z2, NET_ANN, &who2) == 0);
- TEST(ulogin_find_user("user2") != NULL);
- TEST(ulogin_find_user("user1")->user == s1);
- TEST(ulogin_find_user("user2")->user == s2);
+ TEST(ulogin_find_user("user2") != -1);
+ TEST(locations[ulogin_find_user("user1")].user == s1);
+ TEST(locations[ulogin_find_user("user2")].user == s2);
TEST(ulogin_add_user(&z1, NET_ANN, &who1) == 0);
- TEST(ulogin_find_user("user1")->user == s1);
- TEST(ulogin_find_user("user2")->user == s2);
+ TEST(locations[ulogin_find_user("user1")].user == s1);
+ TEST(locations[ulogin_find_user("user2")].user == s2);
who3.sin_family = AF_INET;
who3.sin_port = 3;
who3.sin_addr.s_addr = INADDR_LOOPBACK;
- TEST(ulogin_find("user1", &who3.sin_addr, 3) == NULL);
+ TEST(ulogin_find("user1", &who3.sin_addr, 3) == -1);
who0.sin_family = AF_INET;
who0.sin_port = 3;
@@ -120,9 +121,9 @@ test_uloc() {
s0 = make_string(z0.z_class_inst, 0);
TEST(ulogin_add_user(&z0, NET_ANN, &who0) == 0);
- TEST(ulogin_find_user("user0") != NULL);
- TEST(ulogin_find_user("user1")->user == s1);
- TEST(ulogin_find_user("user2")->user == s2);
+ TEST(ulogin_find_user("user0") != -1);
+ TEST(locations[ulogin_find_user("user1")].user == s1);
+ TEST(locations[ulogin_find_user("user2")].user == s2);
TEST(ulogin_remove_user(&z0, &who0, &ret) == NET_ANN && ret == 0);
/* 1 = NOLOC */
@@ -132,12 +133,12 @@ test_uloc() {
TEST(ulogin_remove_user(&z1, &who0, &ret) == NET_ANN && ret == 0);
V(ulogin_flush_user(&z0));
- TEST(ulogin_find_user("user0") == NULL);
+ TEST(ulogin_find_user("user0") == -1);
TEST(ulogin_add_user(&z0, NET_ANN, &who0) == 0);
TEST(ulogin_add_user(&z1, NET_ANN, &who1) == 0);
V(ulogin_flush_user(&z1));
- TEST(ulogin_find_user("user1") == NULL);
+ TEST(ulogin_find_user("user1") == -1);
who4.sin_family = AF_INET;
who4.sin_port = 4;
@@ -153,14 +154,14 @@ test_uloc() {
TEST(ulogin_add_user(&z4, NET_ANN, &who4) == 0);
V(uloc_flush_client(&who2));
- TEST(ulogin_find_user("user0")->user == s0);
- TEST(ulogin_find_user("user1") == NULL);
- TEST(ulogin_find_user("user2") == NULL);
- TEST(ulogin_find_user("user4")->user == s4);
+ TEST(locations[ulogin_find_user("user0")].user == s0);
+ TEST(ulogin_find_user("user1") == -1);
+ TEST(ulogin_find_user("user2") == -1);
+ TEST(locations[ulogin_find_user("user4")].user == s4);
V(uloc_hflush(&who0.sin_addr));
- TEST(ulogin_find_user("user0") == NULL);
- TEST(ulogin_find_user("user1") == NULL);
- TEST(ulogin_find_user("user2") == NULL);
- TEST(ulogin_find_user("user4")->user == s4);
+ TEST(ulogin_find_user("user0") == -1);
+ TEST(ulogin_find_user("user1") == -1);
+ TEST(ulogin_find_user("user2") == -1);
+ TEST(locations[ulogin_find_user("user4")].user == s4);
}
diff --git a/server/uloc.c b/server/uloc.c
index 0e45bfb..ab936b8 100644
--- a/server/uloc.c
+++ b/server/uloc.c
@@ -68,9 +68,9 @@ static const char rcsid_uloc_c[] =
static void ulogin_locate(ZNotice_t *notice, struct sockaddr_in *who,
int auth);
void ulogin_flush_user(ZNotice_t *notice);
-Location *ulogin_find(char *user, struct in_addr *host,
+int ulogin_find(char *user, struct in_addr *host,
unsigned int port);
-Location *ulogin_find_user(char *user);
+int ulogin_find_user(char *user);
static int ulogin_setup(ZNotice_t *notice, Location *locs,
Exposure_type exposure, struct sockaddr_in *who);
int ulogin_add_user(ZNotice_t *notice, Exposure_type exposure,
@@ -86,8 +86,9 @@ static char **ulogin_marshal_locs(ZNotice_t *notice, int *found, int auth);
static void free_loc(Location *loc);
static void ulogin_locate_forward(ZNotice_t *notice, struct sockaddr_in *who,
ZRealm *realm);
+static int reallocate_locations(int new_num);
-static Location *locations = NULL; /* ptr to first in array */
+Location *locations = NULL; /* ptr to first in array */
static int num_locs = 0; /* number in array */
/*
@@ -284,103 +285,70 @@ ulocate_dispatch(ZNotice_t *notice,
}
/*
+ * reallocate locations
+ */
+static int
+reallocate_locations(int new_num) {
+ Location *new_loc;
+
+ if (new_num) {
+ new_loc = realloc(locations, new_num * sizeof(Location));
+ if (new_loc == NULL) {
+ syslog(LOG_ERR, "failed to resize uloc table: %m");
+ if (new_num < num_locs)
+ num_locs = new_num;
+ return errno;
+ }
+ locations = new_loc;
+ } else {
+ free(locations);
+ locations = NULL;
+ }
+
+ num_locs = new_num;
+
+ return 0;
+}
+
+/*
* Flush all locations at the address.
*/
void
uloc_hflush(struct in_addr *addr)
{
- Location *loc;
- int i = 0, new_num = 0;
+ int i, new_num = 0;
if (num_locs == 0)
return; /* none to flush */
- /* slightly inefficient, assume the worst, and allocate enough space */
- loc = (Location *) malloc(num_locs *sizeof(Location));
- if (!loc) {
- syslog(LOG_CRIT, "uloc_flush alloc");
- abort();
- }
-
- /* copy entries which don't match */
- while (i < num_locs) {
+ for (i = 0; i < num_locs; i++)
if (locations[i].addr.sin_addr.s_addr != addr->s_addr)
- loc[new_num++] = locations[i];
+ locations[new_num++] = locations[i];
else
free_loc(&locations[i]);
- i++;
- }
- free(locations);
- locations = NULL;
-
- if (!new_num) {
- free(loc);
- loc = NULL;
- num_locs = new_num;
-
- return;
- }
- locations = loc;
- num_locs = new_num;
-
- /* all done */
- return;
+ reallocate_locations(new_num);
}
void
uloc_flush_client(struct sockaddr_in *sin)
{
- Location *loc;
- int i = 0, new_num = 0;
+ int i, new_num = 0;
if (num_locs == 0)
return; /* none to flush */
- /* slightly inefficient, assume the worst, and allocate enough space */
- loc = (Location *) malloc(num_locs *sizeof(Location));
- if (!loc) {
- syslog(LOG_CRIT, "uloc_flush_clt alloc");
- abort();
- }
-
- /* copy entries which don't match */
- while (i < num_locs) {
+ for (i = 0; i < num_locs; i++)
if ((locations[i].addr.sin_addr.s_addr != sin->sin_addr.s_addr)
- || (locations[i].addr.sin_port != sin->sin_port)) {
- loc[new_num++] = locations[i];
- } else {
+ || (locations[i].addr.sin_port != sin->sin_port))
+ locations[new_num++] = locations[i];
+ else
free_loc(&locations[i]);
- }
- i++;
- }
- free(locations);
- locations = NULL;
-
- if (!new_num) {
- free(loc);
- loc = NULL;
- num_locs = new_num;
-
- return;
- }
- locations = loc;
num_locs = new_num;
-#ifdef DEBUG
- if (zdebug) {
- int i;
-
- for (i = 0; i < num_locs; i++) {
- syslog(LOG_DEBUG, "%s/%d", locations[i].user->string,
- (int) locations[i].exposure);
- }
- }
-#endif
- /* all done */
- return;
+ reallocate_locations(new_num);
}
/*
@@ -444,71 +412,43 @@ ulogin_add_user(ZNotice_t *notice,
Exposure_type exposure,
struct sockaddr_in *who)
{
- Location *loc, *oldlocs, newloc;
- int i;
+ Location newloc;
+ int i, here;
- loc = ulogin_find(notice->z_class_inst, &who->sin_addr, notice->z_port);
- if (loc) {
+ here = ulogin_find(notice->z_class_inst, &who->sin_addr, notice->z_port);
+ if (here >= 0) {
/* Update the time, tty, and exposure on the existing location. */
- loc->exposure = exposure;
+ locations[here].exposure = exposure;
if (ulogin_parse(notice, &newloc) == 0) {
- free_string(loc->tty);
- loc->tty = dup_string(newloc.tty);
- free(loc->time);
- loc->time = strsave(newloc.time);
+ free_string(locations[here].tty);
+ locations[here].tty = dup_string(newloc.tty);
+ free(locations[here].time);
+ locations[here].time = strsave(newloc.time);
free_loc(&newloc);
}
return 0;
}
- oldlocs = locations;
+ if (ulogin_setup(notice, &newloc, exposure, who))
+ return 1;
- locations = (Location *) malloc((num_locs + 1) * sizeof(Location));
- if (!locations) {
- syslog(LOG_ERR, "zloc mem alloc");
- locations = oldlocs;
- return 1;
- }
+ if(reallocate_locations(num_locs + 1))
+ return 1;
- if (num_locs == 0) { /* first one */
- if (ulogin_setup(notice, locations, exposure, who)) {
- free(locations);
- locations = NULL;
- return 1;
- }
- num_locs = 1;
- goto dprnt;
- }
+ /* skip old locs */
+ for (i = 0;
+ i < num_locs-1 && comp_string(locations[i].user, newloc.user) < 0;
+ i++)
+ ;
- /* not the first one, insert him */
-
- if (ulogin_setup(notice, &newloc, exposure, who)) {
- free(locations);
- locations = oldlocs;
- return 1;
- }
- num_locs++;
-
- /* copy old locs */
- i = 0;
- while ((i < num_locs-1) &&
- (comp_string(oldlocs[i].user,newloc.user) < 0)) {
- locations[i] = oldlocs[i];
- i++;
- }
-
- /* add him in here */
- locations[i++] = newloc;
+ here = i;
/* copy the rest */
- while (i < num_locs) {
- locations[i] = oldlocs[i - 1];
- i++;
- }
- if (oldlocs)
- free(oldlocs);
+ for(i = num_locs - 1; i > here; i--)
+ locations[i] = locations[i - 1];
+
+ locations[here] = newloc;
- dprnt:
return 0;
}
@@ -574,41 +514,39 @@ ulogin_parse(ZNotice_t *notice,
return 0;
}
-
-Location *
+int
ulogin_find(char *user,
struct in_addr *host,
unsigned int port)
{
- Location *loc;
+ int i;
String *str;
/* Find the first location for this user. */
- loc = ulogin_find_user(user);
- if (!loc)
- return NULL;
+ i = ulogin_find_user(user);
+ if (i == -1)
+ return -1;
/* Look for a location which matches the host and port. */
str = make_string(user, 0);
- while (loc < locations + num_locs && loc->user == str) {
- if (loc->addr.sin_addr.s_addr == host->s_addr
- && loc->addr.sin_port == port) {
+ while (i < num_locs && locations[i].user == str) {
+ if (locations[i].addr.sin_addr.s_addr == host->s_addr
+ && locations[i].addr.sin_port == port) {
free_string(str);
- return loc;
+ return i;
}
- loc++;
+ i++;
}
free_string(str);
- return NULL;
+ return -1;
}
/*
- * Return a pointer to the first instance of this user@realm in the
+ * Return the table index of the first instance of this user@realm in the
* table.
*/
-
-Location *
+int
ulogin_find_user(char *user)
{
int i, rlo, rhi;
@@ -616,7 +554,7 @@ ulogin_find_user(char *user)
String *str;
if (!locations)
- return(NULL);
+ return -1;
str = make_string(user, 0);
@@ -634,7 +572,7 @@ ulogin_find_user(char *user)
rhi = i - 1;
if (rhi - rlo < 0) {
free_string(str);
- return NULL;
+ return -1;
}
i = (rhi + rlo) / 2;
}
@@ -643,7 +581,7 @@ ulogin_find_user(char *user)
while (i > 0 && locations[i - 1].user == str)
i--;
free_string(str);
- return &locations[i];
+ return i;
}
/*
@@ -655,51 +593,25 @@ ulogin_remove_user(ZNotice_t *notice,
struct sockaddr_in *who,
int *err_return)
{
- Location *new_locs, *loc;
- int i = 0;
+ int here, i;
Exposure_type quiet;
*err_return = 0;
- loc = ulogin_find(notice->z_class_inst, &who->sin_addr, notice->z_port);
- if (!loc) {
+ here = ulogin_find(notice->z_class_inst, &who->sin_addr, notice->z_port);
+ if (here == -1) {
*err_return = NOLOC;
return NONE;
}
- quiet = loc->exposure;
-
- if (--num_locs == 0) { /* last one */
- free_loc(locations);
- free(locations);
- locations = NULL;
- return quiet;
- }
-
- new_locs = (Location *) malloc(num_locs * sizeof(Location));
- if (!new_locs) {
- syslog(LOG_CRIT, "ul_rem alloc");
- abort();
- }
-
- /* copy old entries */
- while (i < num_locs && &locations[i] < loc) {
- new_locs[i] = locations[i];
- i++;
- }
+ quiet = locations[here].exposure;
/* free up this one */
- free_loc(&locations[i]);
- i++; /* skip over this one */
+ free_loc(&locations[here]);
- /* copy the rest */
- while (i <= num_locs) {
- new_locs[i - 1] = locations[i];
- i++;
- }
+ for(i = here; i < num_locs - 1; i++)
+ locations[i] = locations[i + 1];
- free(locations);
-
- locations = new_locs;
+ reallocate_locations(num_locs - 1);
/* all done */
return quiet;
@@ -712,71 +624,32 @@ ulogin_remove_user(ZNotice_t *notice,
void
ulogin_flush_user(ZNotice_t *notice)
{
- Location *loc, *loc2;
- int i, j, num_match, num_left;
+ int here, i, j, num_match, num_left;
i = num_match = num_left = 0;
- if (!(loc2 = ulogin_find_user(notice->z_class_inst)))
+ here = ulogin_find_user(notice->z_class_inst);
+ if (here == -1)
return;
- /* compute # locations left in the list, after loc2 (inclusive) */
- num_left = num_locs - (loc2 - locations);
+ num_left = num_locs - here;
while (num_left &&
- !strcasecmp(loc2[num_match].user->string,
+ !strcasecmp(locations[here + num_match].user->string,
notice->z_class_inst)) {
/* as long as we keep matching, march up the list */
num_match++;
num_left--;
}
- if (num_locs == num_match) { /* no other locations left */
- for (j = 0; j < num_match; j++)
- free_loc(&locations[j]); /* free storage */
- free (locations);
- locations = NULL;
- num_locs = 0;
- return;
- }
- loc = (Location *) malloc((num_locs - num_match) * sizeof(Location));
- if (!loc) {
- syslog(LOG_CRIT, "ul_rem alloc");
- abort();
- }
-
- /* copy old entries */
- while (i < num_locs && &locations[i] < loc2) {
- loc[i] = locations[i];
- i++;
- }
-
- for(j = 0; j < num_match; j++) {
- free_loc(&locations[i]);
- i++;
- }
+ for (j = 0; j < num_match; j++)
+ free_loc(&locations[here + j]);
/* copy the rest */
- while (i < num_locs) {
- loc[i - num_match] = locations[i];
- i++;
- }
-
- free(locations);
-
- locations = loc;
- num_locs -= num_match;
-
-#ifdef DEBUG
- if (zdebug) {
- int i;
+ for (i = here; i < num_locs - num_match; i++)
+ locations[i] = locations[i + 1];
- for (i = 0; i < num_locs; i++) {
- syslog(LOG_DEBUG, "%s/%d", locations[i].user->string,
- (int) locations[i].exposure);
- }
- }
-#endif
+ reallocate_locations(num_locs - num_match);
}
@@ -826,7 +699,6 @@ ulogin_marshal_locs(ZNotice_t *notice,
int auth)
{
Location **matches = (Location **) 0;
- Location *loc;
char **answer;
int i = 0;
String *inst;
@@ -835,11 +707,9 @@ ulogin_marshal_locs(ZNotice_t *notice,
*found = 0; /* # of matches */
- loc = ulogin_find_user(notice->z_class_inst);
- if (!loc)
- return(NULL);
-
- i = loc - locations;
+ i = ulogin_find_user(notice->z_class_inst);
+ if (i == -1)
+ return NULL;
inst = make_string(notice->z_class_inst,0);
while (i < num_locs && (inst == locations[i].user)) {