00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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
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
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
00365 #define IPAY_MAX_WAIT_TIME 1500000
00366
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;
00377
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
00414
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
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
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
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
00633
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