/* Didn't allocate something, so do nothing */
}
+void
+clients_forget(int fd)
+{
+ struct clientsdb *new_db;
+ struct client *ptr;
+
+ new_db = malloc(sizeof(struct clientsdb));
+ if (new_db == NULL) {
+ warnx("Couldn't allocate new clients DB");
+ return;
+ }
+ clientsdb_init(new_db);
+ read_lock(&rlock, &wlock, &rcounter);
+ ARRAYLIST_FOREACH(&clients_db, ptr)
+ if (ptr->fd != fd)
+ clientsdb_add(new_db, ptr);
+ read_unlock(&rlock, &wlock, &rcounter);
+
+ sem_wait(&wlock);
+ clients_db = *new_db;
+ sem_post(&wlock);
+ free(new_db);
+}
+
void
clients_db_destroy(void)
{
};
int clients_db_init(void);
-int update_client(int fd, struct sockaddr_storage *, u_int8_t);
+int update_client(int, struct sockaddr_storage *, u_int8_t);
size_t client_list(struct client **);
+void clients_forget(int);
void clients_db_destroy(void);
#endif /* SRC_CLIENTS_H_ */
return VERDICT_EXIT;
}
+static void *
+end_client(int client_fd, const struct pdu_metadata *meta, void *pdu)
+{
+ if (meta != NULL && pdu != NULL)
+ meta->destructor(pdu);
+ clients_forget(client_fd);
+ return NULL;
+}
+
/*
* The client socket threads' entry routine.
*
while (loop) { /* For each PDU... */
err = pdu_load(param.client_fd, &pdu, &meta, &rtr_version);
if (err)
- return NULL;
+ return end_client(param.client_fd, NULL, NULL);
/* Protocol Version Negotiation */
if (rtr_version != RTR_VERSION_SUPPORTED) {
err_pdu_send(param.client_fd, RTR_VERSION_SUPPORTED,
ERR_PDU_UNSUP_PROTO_VERSION,
(struct pdu_header *) pdu, NULL);
- meta->destructor(pdu);
- return NULL;
+ return end_client(param.client_fd, meta, pdu);
}
/* RTR Version ready, now update client */
err = update_client(param.client_fd, ¶m.client_addr,
: ERR_PDU_UNEXPECTED_PROTO_VERSION),
(struct pdu_header *) pdu, NULL);
}
- meta->destructor(pdu);
- return NULL;
+ return end_client(param.client_fd, meta, pdu);
}
err = meta->handle(param.client_fd, pdu);
meta->destructor(pdu);
if (err)
- return NULL;
+ return end_client(param.client_fd, NULL, NULL);
}
return NULL; /* Unreachable. */