mn_ipay.c

Go to the documentation of this file.
00001 /* $Id: mn_ipay.c,v 1.7 2001/01/31 22:06:13 jm Exp $
00002  * Mobile Node - Ipay interface routines
00003  *
00004  * Dynamic hierarchial IP tunnel
00005  * Copyright (C) 1998-2001, Dynamics group
00006  *
00007  * This program is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License version 2 as
00009  * published by the Free Software Foundation. See README and COPYING for
00010  * more details.
00011  */
00012 
00013 
00014 #ifdef INCLUDE_IPAY
00015 
00016 #ifdef HAVE_CONFIG_H
00017 #include <config.h>
00018 #endif
00019 
00020 #include <stdlib.h>
00021 #include <sys/types.h>
00022 #include <sys/socket.h>
00023 #include <string.h>
00024 #include <errno.h>
00025 #include <ctype.h>
00026 #include <netinet/in.h>
00027 #include <arpa/inet.h>
00028 
00029 #include "mn.h"
00030 #include "mn_handler.h"
00031 #include "hashtable.h"
00032 #include "debug.h"
00033 #include "ipay-msg.h"
00034 #include "mn_ipay.h"
00035 
00036 
00037 extern struct mn_data mn;
00038 extern struct mn_config config;
00039 
00040 /* the last reported faIdentifier to Ipay buyer (with new FA message) */
00041 static IPAY_CHAR prev_faIdentifier;
00042 
00043 #define DEBUG_IPAY 'i'
00044 
00045 static void show_ipay_char(char *title, char *p)
00046 {
00047         int i;
00048         DEBUG(DEBUG_IPAY, "\t  %s: ", title);
00049         for (i = 0; i < IPAY_CHAR_LEN; i++) {
00050                 if (p[i] == '\0')
00051                         break;
00052                 if (isprint(p[i]))
00053                         DEBUG(DEBUG_IPAY, "%c", p[i]);
00054                 else
00055                         DEBUG(DEBUG_IPAY, "<%u>", (unsigned int) p[i]);
00056         }
00057         DEBUG(DEBUG_IPAY, "\n");
00058 }
00059 
00060 
00061 static int ipay_check_len(int len, int expected)
00062 {
00063         if (len != expected) {
00064                 DEBUG(DEBUG_IPAY, "\t - length mismatch (expected %i bytes)\n",
00065                       expected);
00066                 if (len < expected) {
00067                         DEBUG(DEBUG_IPAY, "\t - too short - cannot parse\n");
00068                         return -1;
00069                 }
00070                 DEBUG(DEBUG_IPAY, "\t - ignoring extra bytes\n");
00071         }
00072         return 0;
00073 }
00074 
00075 
00076 static int send_to_buyer(void *data, int len)
00077 {
00078         struct sockaddr_in addr;
00079         int res;
00080 
00081         if (!mn.ipay_in_use)
00082                 return 0;
00083 
00084         memset(&addr, 0, sizeof(addr));
00085         addr.sin_family = AF_INET;
00086         addr.sin_addr = config.ipay_buyer_addr;
00087         addr.sin_port = htons(config.ipay_buyer_port);
00088 
00089         DEBUG(DEBUG_IPAY, "\tsending %i bytes to %s:%i\n", len,
00090               inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
00091 
00092         res = sendto(mn.ipay_sock, data, len, 0, (struct sockaddr *) &addr,
00093                      sizeof(addr));
00094         if (res < 0) {
00095                 DEBUG(DEBUG_IPAY, "\tsendto - %s\n", strerror(errno));
00096                 return -1;
00097         } else if (res != len) {
00098                 DEBUG(DEBUG_IPAY, "\tsend only %i/%i bytes\n", res, len);
00099                 return -1;
00100         }
00101         return 0;
00102 }
00103 
00104 
00105 static int send_to_fa(void *data, int len)
00106 {
00107         struct sockaddr_in addr;
00108         int res;
00109 
00110         if (!mn.ipay_in_use)
00111                 return 0;
00112 
00113         memset(&addr, 0, sizeof(addr));
00114         addr.sin_family = AF_INET;
00115         addr.sin_addr = mn.fa_addr;
00116         addr.sin_port = htons(config.ipay_fa_port);
00117 
00118         DEBUG(DEBUG_IPAY, "\tsending %i bytes to %s:%i\n", len,
00119               inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
00120 
00121         res = sendto(mn.ipay_sock_fa, data, len, 0, (struct sockaddr *) &addr,
00122                      sizeof(addr));
00123 
00124         if (res < 0) {
00125                 DEBUG(DEBUG_IPAY, "\tsendto - %s\n", strerror(errno));
00126                 return -1;
00127         } else if (res != len) {
00128                 DEBUG(DEBUG_IPAY, "\tsend only %i/%i bytes\n", res, len);
00129                 return -1;
00130         }
00131         return 0;
00132 }
00133 
00134 
00135 static void handle_initialize(int s, char *msg, int len)
00136 {
00137         struct ipay_initialize *ini;
00138         int l;
00139 
00140         DEBUG(DEBUG_IPAY, "\tinitialize message\n");
00141         if (ipay_check_len(len, sizeof(struct ipay_initialize)) < 0)
00142                 return;
00143 
00144         ini = (struct ipay_initialize *) msg;
00145 
00146         show_ipay_char("mnIdentifier", ini->mnIdentifier);
00147 
00148         l = 0;
00149         while (l < IPAY_CHAR_LEN && ini->mnIdentifier[l] != '\0')
00150                 l++;
00151         if (l == 0) {
00152                 DEBUG(DEBUG_IPAY, "\tzero length NAI - ignoring\n");
00153                 return;
00154         }
00155         if (mn.nai.nai != NULL)
00156                 free(mn.nai.nai);
00157         mn.nai.nai = malloc(l);
00158         if (mn.nai.nai == NULL) {
00159                 DEBUG(DEBUG_IPAY, "\tmalloc failed\n");
00160                 mn.nai.len = 0;
00161                 return;
00162         }
00163         mn.nai.len = l;
00164         memcpy(mn.nai.nai, ini->mnIdentifier, l);
00165 
00166         mn.ipay_in_use = 1;
00167         ipay_flush_priority_cache(0);
00168 }
00169 
00170 
00171 static int prio_avail = 0;
00172 static __u32 last_prio = 0;
00173 
00174 static void handle_policy_prio_reply(int s, char *msg, int len)
00175 {
00176         struct ipay_policy_prio_reply *prio;
00177 
00178         DEBUG(DEBUG_IPAY, "\tpolicy prio reply message\n");
00179         if (ipay_check_len(len, sizeof(struct ipay_policy_prio_reply)) < 0)
00180                 return;
00181 
00182         prio = (struct ipay_policy_prio_reply *) msg;
00183         DEBUG(DEBUG_IPAY, "\tpriority=%u\n", ntohl(prio->priority));
00184 
00185         prio_avail = 1;
00186         last_prio = ntohl(prio->priority);
00187 }
00188 
00189 
00190 static void handle_purchase(int s, char *msg, int len)
00191 {
00192         struct ipay_purchase *pur;
00193 
00194         DEBUG(DEBUG_IPAY, "\tpurchase message\n");
00195         if (ipay_check_len(len, sizeof(struct ipay_purchase)) < 0)
00196                 return;
00197 
00198         pur = (struct ipay_purchase *) msg;
00199 
00200         DEBUG(DEBUG_IPAY, "\t  timeStamp: %u\n", ntohl(pur->timeStamp));
00201         show_ipay_char("mnIdentifier", pur->mnIdentifier);
00202         show_ipay_char("faIdentifier", pur->faIdentifier);
00203         DEBUG(DEBUG_IPAY, "\t  purchaseSerialNumber: %u\n",
00204               ntohl(pur->purchaseSerialNumber));
00205         DEBUG(DEBUG_IPAY, "\t  microPaymentUnit: %u\n",
00206               ntohl(pur->microPaymentUnit));
00207         DEBUG(DEBUG_IPAY, "\t  maxNumberOfUnits: %u\n",
00208               ntohl(pur->maxNumberOfUnits));
00209         show_ipay_char("firstPayment", pur->firstPayment);
00210         DEBUG(DEBUG_IPAY, "\t  timePrice: %u\n", ntohl(pur->timePrice));
00211         DEBUG(DEBUG_IPAY, "\t  bytePrice: %u\n", ntohl(pur->bytePrice));
00212         show_ipay_char("signature", pur->signature);
00213 
00214         send_to_fa(pur, len);
00215 }
00216 
00217 
00218 static void handle_allowance(int s, char *msg, int len)
00219 {
00220         struct ipay_allowance *allow;
00221 
00222         DEBUG(DEBUG_IPAY, "\tallowance message\n");
00223         if (ipay_check_len(len, sizeof(struct ipay_allowance)))
00224                 return;
00225 
00226         allow = (struct ipay_allowance *) msg;
00227 
00228         DEBUG(DEBUG_IPAY, "\t  allowance: %u\n", ntohl(allow->allowance));
00229         show_ipay_char("mnIdentifier", allow->mnIdentifier);
00230         DEBUG(DEBUG_IPAY, "\t  timePrice: %u\n", ntohl(allow->timePrice));
00231         DEBUG(DEBUG_IPAY, "\t  bytePrice: %u\n", ntohl(allow->bytePrice));
00232         DEBUG(DEBUG_IPAY, "\t  apporovedNumberOfUnits: %u\n",
00233               ntohl(allow->approvedNumberOfUnits));
00234         show_ipay_char("sessionKey", allow->sessionKey);
00235         show_ipay_char("signature", allow->signature);
00236 
00237         send_to_buyer(msg, len);
00238 
00239         if (!ntohl(allow->allowance)) {
00240                 DEBUG(DEBUG_IPAY, "\tconnection to FA not allowed => marking "
00241                       "FA unusable\n");
00242                 if (mn.current_adv != NULL) {
00243                         mn.current_adv->priority = 0;
00244                         mn.current_adv->reg_failed = 1;
00245                 }
00246                 find_agent(STATE_INIT);
00247         }
00248 }
00249 
00250 static void handle_please_pay_more(int s, char *msg, int len)
00251 {
00252         struct ipay_please_pay_more *pay;
00253         struct ipay_statistics stat;
00254         static time_t prev_stat = 0;
00255         time_t now;
00256 
00257         DEBUG(DEBUG_IPAY, "\tplease pay more message\n");
00258         if (ipay_check_len(len, sizeof(struct ipay_please_pay_more)))
00259                 return;
00260 
00261         pay = (struct ipay_please_pay_more *) msg;
00262 
00263         show_ipay_char("mnIdentifier", pay->mnIdentifier);
00264         DEBUG(DEBUG_IPAY, "\t  usedTime: %u\n", ntohl(pay->usedTime));
00265         DEBUG(DEBUG_IPAY, "\t  usedByte: %u\n", ntohl(pay->usedByte));
00266         show_ipay_char("sessionKey", pay->sessionKey);
00267         show_ipay_char("signature", pay->signature);
00268 
00269         memset(&stat, 0, sizeof(stat));
00270         stat.type = htonl(IPAY_MSG_STATISTICS);
00271         if (mn.current_adv != NULL) {
00272                 struct fa_nai_ext *nai;
00273                 nai = (struct fa_nai_ext *) mn.current_adv->fa_nai;
00274                 memcpy(stat.faIdentifier, MSG_NAI_DATA(nai),
00275                        MIN(IPAY_CHAR_LEN, GET_NAI_LEN(nai)));
00276         }
00277         /* FIX statistics */
00278         stat.bytes = htonl(0);
00279         time(&now);
00280         if (prev_stat == 0 || now < prev_stat) {
00281                 stat.time = htonl(0);
00282                 prev_stat = now;
00283         } else {
00284                 stat.time = htonl(now - prev_stat);
00285                 prev_stat = now;
00286         }
00287         DEBUG(DEBUG_IPAY, "\tsending statistics (bytes=%u, time=%u)\n",
00288               ntohl(stat.bytes), ntohl(stat.time));
00289         send_to_buyer(&stat, sizeof(stat));
00290         DEBUG(DEBUG_IPAY, "\tforwarding please pay more\n");
00291         send_to_buyer(msg, len);
00292 }
00293 
00294 
00295 static void handle_micro_payment(int s, char *msg, int len)
00296 {
00297         struct ipay_micro_payment *pay;
00298 
00299         DEBUG(DEBUG_IPAY, "\tmicro payment message\n");
00300         if (ipay_check_len(len, sizeof(struct ipay_micro_payment)) < 0)
00301                 return;
00302 
00303         pay = (struct ipay_micro_payment *) msg;
00304 
00305         show_ipay_char("mnIdentifier", pay->mnIdentifier);
00306         show_ipay_char("nextPayment", pay->nextPayment);
00307 
00308         send_to_fa(msg, len);
00309 }
00310 
00311 
00312 void handle_ipay(int s)
00313 {
00314         char msg[MAXMSG];
00315         struct sockaddr_in from;
00316         int fromlen, len;
00317         IPAY_TYPE *type;
00318 
00319         DEBUG(DEBUG_IPAY, "Ipay message from socket %i\n", s);
00320 
00321         fromlen = sizeof(from);
00322         len = recvfrom(s, msg, MAXMSG, 0, (struct sockaddr *) &from, &fromlen);
00323         if (len < 0) {
00324                 DEBUG(DEBUG_IPAY, "\trecvfrom failed - %s\n", strerror(errno));
00325                 return;
00326         }
00327         DEBUG(DEBUG_IPAY, "\t%i bytes from %s:%i\n", len,
00328               inet_ntoa(from.sin_addr), ntohs(from.sin_port));
00329 
00330         if (len < sizeof(IPAY_TYPE)) {
00331                 DEBUG(DEBUG_IPAY, "\ttoo short message - ignoring it\n");
00332                 return;
00333         }
00334         type = (IPAY_TYPE *) msg;
00335         DEBUG(DEBUG_IPAY, "\ttype=%i\n", ntohl(*type));
00336 
00337         switch (ntohl(*type)) {
00338         case IPAY_MSG_INITIALIZE:
00339                 handle_initialize(s, msg, len);
00340                 break;
00341         case IPAY_MSG_POLICY_REPLY:
00342                 handle_policy_prio_reply(s, msg, len);
00343                 break;
00344         case IPAY_MSG_PURCHASE:
00345                 handle_purchase(s, msg, len);
00346                 break;
00347         case IPAY_MSG_ALLOWANCE:
00348                 handle_allowance(s, msg, len);
00349                 break;
00350         case IPAY_MSG_PLEASE_PAY_MORE:
00351                 handle_please_pay_more(s, msg, len);
00352                 break;
00353         case IPAY_MSG_MICRO_PAYMENT:
00354                 handle_micro_payment(s, msg, len);
00355                 break;
00356         default:
00357                 DEBUG(DEBUG_IPAY, "\tunknown message type - ignoring "
00358                       "message\n");
00359                 break;
00360         }
00361 }
00362 
00363 
00364 /* maximum wait time for 'blocking' prio req call in usecs */
00365 #define IPAY_MAX_WAIT_TIME 1500000
00366 /* policy request retry time in seconds */
00367 #define IPAY_RETRY_TIME 120
00368 
00369 struct prio_cache_data {
00370         struct node node;
00371         __u32 timePrice;
00372         __u32 bytePrice;
00373         __u32 priority;
00374 
00375         time_t req_time;
00376         int reply_ok; /* whether a reply was received or not; if not, retry
00377                        * after IPAY_RETRY_TYIME seconds */
00378 };
00379 
00380 #define PRIO_CACHE_SIZE 19
00381 static struct hashtable *prio_cache = NULL;
00382 
00383 static int
00384 prio_hash(void *key, const int hashsize)
00385 {
00386         int res;
00387         struct prio_cache_data *data = (struct prio_cache_data *) key;
00388         res = (data->timePrice + data->bytePrice) % PRIO_CACHE_SIZE;
00389         return (unsigned) res;
00390 }
00391 
00392 static int
00393 prio_cmp(void *key, struct node *cmprd)
00394 {
00395         struct prio_cache_data *prio1, *prio2;
00396 
00397         prio1 = (struct prio_cache_data *) key;
00398         prio2 = (struct prio_cache_data *) cmprd;
00399 
00400         if (prio1->timePrice == prio2->timePrice &&
00401             prio1->bytePrice == prio2->bytePrice)
00402                 return 1;
00403         return 0;
00404 }
00405 
00406 static void
00407 wait_for_reply(void)
00408 {
00409         fd_set set;
00410         struct timeval tv, start, now;
00411         int diff;
00412 
00413         /* wait for the reply for a limited time and also process any other
00414          * Ipay messages */
00415 
00416         gettimeofday(&start, NULL);
00417         diff = 0;
00418 
00419         for (;;) {
00420                 tv.tv_sec = (IPAY_MAX_WAIT_TIME - diff) / 1000000;
00421                 tv.tv_usec = (IPAY_MAX_WAIT_TIME - diff) % 1000000;
00422                 DEBUG(DEBUG_IPAY, "\twaiting for Ipay reply - timeout %i sec "
00423                       "%i usec\n", tv.tv_sec, tv.tv_usec);
00424 
00425                 FD_ZERO(&set);
00426                 FD_SET(mn.ipay_sock, &set);
00427 
00428                 select(mn.ipay_sock + 1, &set, NULL, NULL, &tv);
00429                 if (FD_ISSET(mn.ipay_sock, &set))
00430                         handle_ipay(mn.ipay_sock);
00431 
00432                 if (prio_avail)
00433                         return;
00434 
00435                 gettimeofday(&now, NULL);
00436                 diff = (now.tv_sec - start.tv_sec) * 1000000 + now.tv_usec -
00437                         start.tv_usec;
00438                 if (diff < 0) {
00439                         DEBUG(DEBUG_IPAY, "Clock changed?\n");
00440                         return;
00441                 }
00442                 if (diff >= IPAY_MAX_WAIT_TIME) {
00443                         DEBUG(DEBUG_IPAY, "Timeout while waiting a reply from "
00444                               "Ipay buyer\n");
00445                               return;
00446                 }
00447         }
00448 }
00449 
00450 
00451 __u32 ipay_get_priority(__u32 timePrice, __u32 bytePrice)
00452 {
00453         struct prio_cache_data *entry = NULL, key;
00454         struct ipay_policy_prio_req req;
00455         int update_entry = 0;
00456 
00457         if (!mn.ipay_in_use)
00458                 return 1;
00459 
00460         if (prio_cache != NULL) {
00461                 memset(&key, 0, sizeof(key));
00462                 key.timePrice = timePrice;
00463                 key.bytePrice = bytePrice;
00464                 if (prio_cache == NULL) {
00465                         DEBUG(DEBUG_IPAY, "prio_cache == NULL\n");
00466                         entry = NULL;
00467                 } else {
00468                         entry = (struct prio_cache_data *)
00469                                 hashtable_fetch(prio_cache, prio_hash, &key,
00470                                                 prio_cmp);
00471                 }
00472                 if (entry != NULL &&
00473                     (entry->reply_ok ||
00474                      time(NULL) < entry->req_time + IPAY_RETRY_TIME)) {
00475                         DEBUG(DEBUG_IPAY, "ipay_get_priority - prio=%u "
00476                               "(from cache)\n", entry->priority);
00477                         return entry->priority;
00478                 }
00479                 update_entry = 1;
00480         } else {
00481                 prio_cache = hashtable_init(PRIO_CACHE_SIZE);
00482                 if (prio_cache == NULL) {
00483                         DEBUG(DEBUG_IPAY, "Priority cache initialization "
00484                               "failed\n");
00485                         return 1;
00486                 }
00487         }
00488 
00489         /* ask policy priority from Ipay Buyer */
00490         prio_avail = 0;
00491 
00492         memset(&req, 0, sizeof(req));
00493         req.type = htonl(IPAY_MSG_POLICY_REQ);
00494         req.timePrice = htonl(timePrice);
00495         req.bytePrice = htonl(bytePrice);
00496 
00497         if (send_to_buyer(&req, sizeof(req)) < 0)
00498                 return 1;
00499 
00500         wait_for_reply();
00501 
00502         /* save the result */
00503         if (!update_entry || entry == NULL) {
00504                 entry = (struct prio_cache_data *)
00505                         malloc(sizeof(struct prio_cache_data));
00506                 if (entry == NULL) {
00507                         DEBUG(DEBUG_IPAY,
00508                               "ipay_get_priority - malloc failed\n");
00509                         return 1;
00510                 }
00511         }
00512 
00513         memset(entry, 0, sizeof(struct prio_cache_data));
00514         entry->timePrice = timePrice;
00515         entry->bytePrice = bytePrice;
00516         time(&entry->req_time);
00517 
00518         if (!prio_avail) {
00519                 DEBUG(DEBUG_IPAY, "No priority reply received in time - "
00520                       "assuming priority 1\n");
00521                 entry->priority = 1;
00522         } else {
00523                 entry->priority = last_prio;
00524                 entry->reply_ok = 1;
00525         }
00526 
00527         if (!update_entry) {
00528                 list_init_node(&entry->node);
00529                 hashtable_add(prio_cache, prio_hash, &entry, &entry->node);
00530         }
00531 
00532         return entry->priority;
00533 }
00534 
00535 static int remove_prio(struct node *node, void *data)
00536 {
00537         hashtable_remove(node);
00538         return 1;
00539 }
00540 
00541 void ipay_flush_priority_cache(int free_mem)
00542 {
00543         if (prio_cache == NULL)
00544                 return;
00545         hashtable_iterator(prio_cache, remove_prio, NULL);
00546         if (free_mem) {
00547                 hashtable_destroy(prio_cache);
00548                 prio_cache = NULL;
00549         }
00550 }
00551 
00552 
00553 void ipay_new_fa(struct agentadv_data *adv)
00554 {
00555         struct ipay_new_fa new;
00556         int len, i;
00557         struct fa_nai_ext *nai;
00558         unsigned char *c;
00559 
00560         if (adv->adv.own_ext == NULL)
00561                 return;
00562         if (strncmp(adv->fa_nai, prev_faIdentifier, IPAY_CHAR_LEN) == 0) {
00563                 DEBUG(DEBUG_IPAY, "ipay_new_fa - using same FA - no report\n");
00564                 return;
00565         }
00566 
00567         nai = (struct fa_nai_ext *) adv->fa_nai;
00568         DEBUG(DEBUG_IPAY, "ipay_new_fa - reporting FA[");
00569         c = MSG_NAI_DATA(nai);
00570         for (i = 0; i < GET_NAI_LEN(nai); i++) {
00571                 if (*c < 32 || *c > 126)
00572                         DEBUG(DEBUG_IPAY, "<%i>", *c);
00573                 else
00574                         DEBUG(DEBUG_IPAY, "%c", *c);
00575                 c++;
00576         }
00577         DEBUG(DEBUG_IPAY, "], timePrice=%i, bytePrice=%i\n",
00578               ntohl(adv->adv.own_ext->timePrice),
00579               ntohl(adv->adv.own_ext->bytePrice));
00580 
00581         memset(&new, 0, sizeof(new));
00582         new.type = htonl(IPAY_MSG_NEW_FA);
00583         len = GET_NAI_LEN(nai);
00584         if (len > IPAY_CHAR_LEN) {
00585                 DEBUG(DEBUG_IPAY, "\ttoo long FA NAI\n");
00586                 len = IPAY_CHAR_LEN;
00587         }
00588         memcpy(new.faIdentifier, MSG_NAI_DATA(nai), len);
00589         new.timePrice = adv->adv.own_ext->timePrice;
00590         new.bytePrice = adv->adv.own_ext->bytePrice;
00591 
00592         send_to_buyer(&new, sizeof(new));
00593 }
00594 
00595 
00596 static int ipay_set_priority(struct node *node, void *data)
00597 {
00598         __u32 prio;
00599         struct agentadv_data *adv = (struct agentadv_data *) node;
00600 
00601         if (adv->adv.own_ext == NULL ||
00602             (ntohs(adv->ext->opts) & AGENT_ADV_FOREIGN_AGENT) == 0)
00603                 return 1;
00604 
00605         DEBUG(DEBUG_IPAY, "ipay_get_priority: time=%i byte=%i\n",
00606               ntohl(adv->adv.own_ext->timePrice),
00607               ntohl(adv->adv.own_ext->bytePrice));
00608         prio = ipay_get_priority(ntohl(adv->adv.own_ext->timePrice),
00609                                  ntohl(adv->adv.own_ext->bytePrice));
00610 
00611         if (prio == 0 && adv->priority > 0) {
00612                 DEBUG(DEBUG_IPAY, "ipay_set_priority - marking FA unusable "
00613                       "(prio: %i ==> 0)\n", adv->priority);
00614         }
00615 
00616         /* FIX: adjust edata->adv->priority somehow according to Ipay prio */
00617 
00618         return 1;
00619 }
00620 
00621 static int ipay_handle_get_fa(void *data)
00622 {
00623         struct event_FA *edata = (struct event_FA *) data;
00624 
00625         hashtable_iterator(edata->hash, ipay_set_priority, NULL);
00626 
00627         return 0;
00628 }
00629 
00630 static int ipay_handle_iface(void *data)
00631 {
00632         /* quick hack to make sure that Ipay handler is after monitor handler.
00633          * Handler priorities would be a nicer solution.. */
00634         handler_unregister(FA_GET, ipay_handle_get_fa);
00635         handler_register(FA_GET, ipay_handle_get_fa);
00636 
00637         return 0;
00638 }
00639 
00640 
00641 void ipay_init(void)
00642 {
00643         handler_register(FA_GET, ipay_handle_get_fa);
00644         handler_register(INTERFACE_INIT, ipay_handle_iface);
00645 }
00646 
00647 void ipay_cleanup(void)
00648 {
00649         handler_unregister(FA_GET, ipay_handle_get_fa);
00650         handler_unregister(INTERFACE_INIT, ipay_handle_iface);
00651 }
00652 
00653 #endif

Generated on Tue Jan 15 08:50:43 2008 for Virtual foreign agent generator version 0.1 by  doxygen 1.5.1