PACKET_FLAG_ERROR = 0xFF, /*!< Invalid flag */
};
-#define PACKET_VERSION 1
+#define PACKET_VERSION 2
#define PACKET_MAX_CMD 24
extern struct packet *packet_create(const char *command, const char *fmt, ...);
extern const void * const packet_data(const struct packet *packet);
extern const double const packet_seq(const struct packet *packet);
extern const enum packet_type const packet_type(const struct packet *packet);
+
extern const enum packet_flag const packet_flag(const struct packet *packet);
+extern int packet_set_flag(struct packet *packet, enum packet_flag flag);
+extern const unsigned long const packet_source(const struct packet *packet);
+extern int packet_set_source(struct packet *packet, unsigned long source);
+extern const unsigned long const packet_destination(const struct packet *packet);
+extern int packet_set_destination(struct packet *packet, unsigned long destination);
+extern int packet_set_mask(struct packet *packet, unsigned long mask);
+extern unsigned long packet_mask(const struct packet *packet);
+
extern const int const packet_version(const struct packet *packet);
extern const int const packet_payload_size(const struct packet *packet);
extern const char * const packet_command(const const struct packet *packet);
};
struct route {
- int from;
- int to;
+ unsigned long address;
+ int handle;
+ int invalid;
};
struct client {
struct dlist *l;
struct dlist *n;
struct event_item *item;
+ struct route *route;
int ret;
+ /*!
+ * Update the routing table.
+ */
+ ret = pthread_mutex_lock(&router->route_list_lock);
+ if (ret != 0)
+ ErrPrint("Failed to lock: %s\n", strerror(ret));
+
+ dlist_foreach(router->route_list, l, route) {
+ if (route->handle == handle)
+ route->invalid = 1;
+ }
+
+ ret = pthread_mutex_unlock(&router->route_list_lock);
+ if (ret != 0)
+ ErrPrint("Failed to unlock: %s\n", strerror(ret));
+
+ /*!
+ * Invoke the disconnected callback
+ */
dlist_foreach_safe(s_info.disconnected_list, l, n, item) {
ret = item->evt_cb(handle, item->data);
if (ret < 0 && dlist_find_data(s_info.disconnected_list, item)) {
* \NOTE
* Running thread: Client / Server leaf thread
*/
-static inline int route_packet(struct router *router, int from, struct packet *packet)
+static inline int route_packet(struct router *router, int handle, struct packet *packet)
{
struct dlist *l;
struct route *route;
- int processed;
- int ret;
+ unsigned long destination;
+ unsigned long source;
+ unsigned long mask;
+ int status;
+ int processed = 0;
- processed = 0;
- dlist_foreach(router->route_list, l, route) {
- if (route->from != from)
- continue;
+ destination = packet_destination(packet);
+ source = packet_destination(packet);
+ mask = packet_mask(packet);
- if (route->to < 0)
- continue;
+ /*!
+ * Can we believe this source?
+ */
- ret = com_core_send(route->to, (void *)packet_data(packet), packet_size(packet), router->timeout);
- if (ret != packet_size(packet)) {
- ErrPrint("Failed to send whole packet\n");
- continue;
+ if (destination && source) {
+ status = pthread_mutex_lock(&router->route_list_lock);
+ if (status != 0)
+ ErrPrint("Failed to lock: %s\n", strerror(status));
+
+ dlist_foreach(router->route_list, l, route) {
+ if (!route->invalid && (route->address & mask) == (destination & mask)) {
+ int ret;
+
+ /*!
+ * This code is executed in the CRITICAL SECTION
+ * If possible, we have to do this from the out of the CRITICAL SECTION
+ *
+ * This code can makes the system slow.
+ *
+ * We have to optimize the processing time in the CRITICAL SECTION
+ */
+ ret = com_core_send(route->handle, (void *)packet_data(packet), packet_size(packet), router->timeout);
+ if (ret != packet_size(packet)) {
+ ErrPrint("Failed to send whole packet\n");
+ }
+
+ processed++;
+ }
}
- processed++;
+ status = pthread_mutex_unlock(&router->route_list_lock);
+ if (status != 0)
+ ErrPrint("Failed to unlock: %s\n", strerror(status));
}
- if (processed == 0)
+ if (processed == 0) {
+ DbgPrint("Drop a packet\n");
router->count_of_dropped_packet++;
+ }
packet_destroy(packet);
return 0;
* \NOTE
* Running thread: Main
*/
-EAPI int com_core_packet_router_add_link(int handle, int from, int to)
+EAPI int com_core_packet_router_add_route(int handle, unsigned long address, int h)
{
struct router *router;
struct route *route;
int status;
+ if (handle < 0 || !address || h < 0)
+ return -EINVAL;
+
router = find_router_by_handle(handle);
if (!router) {
ErrPrint("Router is not exists\n");
return -ENOMEM;
}
- route->from = from;
- route->to = to;
+ route->address = address;
+ route->handle = h;
+ route->invalid = 0;
status = pthread_mutex_lock(&router->route_list_lock);
if (status != 0)
* \NOTE
* Running thread: Main
*/
-EAPI int com_core_packet_router_del_link_by_from(int handle, int from)
+EAPI int com_core_packet_router_del_route(int handle, unsigned long address)
{
struct router *router;
struct route *route;
struct dlist *n;
int status;
+ if (handle < 0 || !address)
+ return -EINVAL;
+
router = find_router_by_handle(handle);
if (!router) {
ErrPrint("Router is not exists\n");
ErrPrint("Failed to lock: %s\n", strerror(status));
dlist_foreach_safe(router->route_list, l, n, route) {
- if (route->from != from)
+ if (route->address != address)
continue;
router->route_list = dlist_remove(router->route_list, l);
- DbgPrint("Delete an entry from the table (%d <-> %d)\n", route->from, route->to);
+ DbgPrint("Delete an entry from the table (%lu : %d)\n", route->address, route->handle);
free(route);
+ break;
}
status = pthread_mutex_unlock(&router->route_list_lock);
return 0;
}
-/*!
- * \NOTE
- * Running thread: Main
- */
-EAPI int com_core_packet_router_del_link_by_to(int handle, int to)
+EAPI int com_core_packet_router_update_route(int handle, unsigned long address, int h)
{
struct router *router;
struct route *route;
struct dlist *l;
- struct dlist *n;
int status;
+ int found = 0;
+
+ if (handle < 0 || !address || h < 0)
+ return -EINVAL;
router = find_router_by_handle(handle);
if (!router) {
if (status != 0)
ErrPrint("Failed to lock: %s\n", strerror(status));
- dlist_foreach_safe(router->route_list, l, n, route) {
- if (route->to != to)
+ dlist_foreach(router->route_list, l, route) {
+ if (route->address != address)
continue;
- router->route_list = dlist_remove(router->route_list, l);
- DbgPrint("Delete an entry from the table (%d <-> %d)\n", route->from, route->to);
- free(route);
+ route->handle = h;
+ route->invalid = 0;
+ found = 1;
+ break;
}
status = pthread_mutex_unlock(&router->route_list_lock);
if (status != 0)
ErrPrint("Failed to unlock: %s\n", strerror(status));
- return 0;
+ return found ? 0 : -ENOENT;
}
/*!
enum packet_type type;
enum packet_flag flag;
double seq;
+ unsigned long source;
+ unsigned long destination;
+ unsigned long mask;
} head;
char payload[];
return packet->data->head.type;
}
+EAPI unsigned long packet_mask(const struct packet *packet)
+{
+ if (!packet || packet->state != VALID || !packet->data)
+ return 0;
+
+ return packet->data->head.mask;
+}
+
+EAPI int packet_set_mask(struct packet *packet, unsigned long mask)
+{
+ if (!packet || packet->state != VALID || !packet->data)
+ return -EINVAL;
+
+ packet->data->head.mask = mask;
+ return 0;
+}
+
EAPI const enum packet_flag const packet_flag(const struct packet *packet)
{
if (!packet || packet->state != VALID || !packet->data)
return packet->data->head.flag;
}
+EAPI int packet_set_flag(struct packet *packet, enum packet_flag flag)
+{
+ if (!packet || packet->state != VALID || !packet->data)
+ return -EINVAL;
+
+ packet->data->head.flag = flag;
+ return 0;
+}
+
+EAPI const unsigned long const packet_source(const struct packet *packet)
+{
+ if (!packet || packet->state != VALID || !packet->data)
+ return 0;
+
+ return packet->data->head.source;
+}
+
+EAPI int packet_set_source(struct packet *packet, unsigned long source)
+{
+ if (!packet || packet->state != VALID || !packet->data || !source)
+ return -EINVAL;
+
+ packet->data->head.source = source;
+ return 0;
+}
+
+EAPI const unsigned long const packet_destination(const struct packet *packet)
+{
+ if (!packet || packet->state != VALID || !packet->data)
+ return 0;
+
+ return packet->data->head.destination;
+}
+
+EAPI int packet_set_destination(struct packet *packet, unsigned long destination)
+{
+ if (!packet || packet->state != VALID || !packet->data || !destination)
+ return -EINVAL;
+
+ packet->data->head.destination = destination;
+ return 0;
+}
+
EAPI const int const packet_version(const struct packet *packet)
{
if (!packet || packet->state != VALID || !packet->data)
}
result->state = VALID;
+
+ result->data->head.source = 0lu;
+ result->data->head.destination = 0lu;
+ result->data->head.mask = 0xFFFFFFFF;
+
result->data->head.seq = packet->data->head.seq;
result->data->head.type = PACKET_ACK;
result->data->head.version = packet->data->head.version;
packet->state = VALID;
gettimeofday(&tv, NULL);
+ packet->data->head.source = 0lu;
+ packet->data->head.destination = 0lu;
+ packet->data->head.mask = 0xFFFFFFFF;
packet->data->head.seq = tv.tv_sec + tv.tv_usec / 1000000.0f;
packet->data->head.type = PACKET_REQ;
packet->data->head.version = PACKET_VERSION;
result->state = VALID;
gettimeofday(&tv, NULL);
+ result->data->head.source = 0lu;
+ result->data->head.destination = 0lu;
+ result->data->head.mask = 0xFFFFFFFF;
result->data->head.seq = tv.tv_sec + tv.tv_usec / 1000000.0f;
result->data->head.type = PACKET_REQ_NOACK;
result->data->head.version = PACKET_VERSION;
packet->state = VALID;
memcpy(packet->data, data, size);
+ packet->data->head.mask = 0xFFFFFFFF;
return packet;
}