Subversion Repositories HelenOS

Rev

Rev 2877 | Rev 2880 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /** @addtogroup sctrace
  2.  * @{
  3.  */
  4. /** @file
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <libadt/hash_table.h>
  10.  
  11. #include "ipc_desc.h"
  12. #include "proto.h"
  13. #include "ipcp.h"
  14.  
  15. #define IPCP_CALLID_SYNC 0
  16.  
  17. typedef struct {
  18.     int phone_hash;
  19.     ipc_call_t question;
  20.  
  21.     int call_hash;
  22.  
  23.     link_t link;
  24. } pending_call_t;
  25.  
  26. typedef struct {
  27.     int server;
  28.     proto_t *proto;
  29. } connection_t;
  30.  
  31. #define MAX_PHONE 64
  32. connection_t connections[MAX_PHONE];
  33. int have_conn[MAX_PHONE];
  34.  
  35. #define PCALL_TABLE_CHAINS 32
  36. hash_table_t pending_calls;
  37.  
  38. hash_index_t pending_call_hash(unsigned long key[])
  39. {
  40. //  printf("pending_call_hash\n");
  41.     return key[0] % PCALL_TABLE_CHAINS;
  42. }
  43.  
  44. int pending_call_compare(unsigned long key[], hash_count_t keys,
  45.     link_t *item)
  46. {
  47.     pending_call_t *hs;
  48.  
  49. //  printf("pending_call_compare\n");
  50.     hs = hash_table_get_instance(item, pending_call_t, link);
  51.  
  52.     return key[0] == hs->call_hash;
  53. }
  54.  
  55. void pending_call_remove_callback(link_t *item)
  56. {
  57. //  printf("pending_call_remove_callback\n");
  58. }
  59.  
  60. hash_table_operations_t pending_call_ops = {
  61.     .hash = pending_call_hash,
  62.     .compare = pending_call_compare,
  63.     .remove_callback = pending_call_remove_callback
  64. };
  65.  
  66. static void connection_set(int phone, int server, proto_t *proto)
  67. {
  68.     if (phone <0 || phone >= MAX_PHONE) return;
  69.     connections[phone].server = server;
  70.     connections[phone].proto = proto;
  71.     have_conn[phone] = 1;
  72. }
  73.  
  74. static void connection_clear(int phone)
  75. {
  76.     have_conn[phone] = 0;
  77.     connections[phone].server = 0;
  78.     connections[phone].proto = NULL;
  79. }
  80.  
  81. static void ipc_m_print(ipcarg_t method)
  82. {
  83.     ipc_m_desc_t *desc;
  84.  
  85.     /* FIXME: too slow */
  86.     desc = ipc_methods;
  87.     while (desc->number != 0) {
  88.         if (desc->number == method) {
  89.             printf("%s (%d)", desc->name, method);
  90.             return;
  91.         }
  92.  
  93.         ++desc;
  94.     }
  95.  
  96.     printf("%d", method);
  97. }
  98.  
  99. void ipcp_init(void)
  100. {
  101.     hash_table_create(&pending_calls, PCALL_TABLE_CHAINS, 1, &pending_call_ops);
  102. }
  103.  
  104. void ipcp_cleanup(void)
  105. {
  106.     hash_table_destroy(&pending_calls);
  107. }
  108.  
  109. void ipcp_call_out(int phone, ipc_call_t *call, ipc_callid_t hash)
  110. {
  111.     pending_call_t *pcall;
  112.     char *proto_name;
  113.  
  114.     if (have_conn[phone]) proto_name = connections[phone].proto->name;
  115.     else proto_name = "n/a";
  116.  
  117. //  printf("ipcp_call_out()\n");
  118.     printf("call id: 0x%x, phone: %d, proto: %s, method: ", hash, phone,
  119.         proto_name);
  120.     ipc_m_print(IPC_GET_METHOD(*call));
  121.     printf(" args: (%u, %u, %u, %u, %u)\n",
  122.         IPC_GET_ARG1(*call),
  123.         IPC_GET_ARG2(*call),
  124.         IPC_GET_ARG3(*call),
  125.         IPC_GET_ARG4(*call),
  126.         IPC_GET_ARG5(*call)
  127.     );
  128.  
  129.     /* Store call in hash table for response matching */
  130.  
  131.     pcall = malloc(sizeof(pending_call_t));
  132.     pcall->phone_hash = phone;
  133.     pcall->question = *call;
  134.     pcall->call_hash = hash;
  135.  
  136.     hash_table_insert(&pending_calls, &pcall->call_hash, &pcall->link);
  137. }
  138.  
  139. static void parse_answer(pending_call_t *pcall, ipc_call_t *answer)
  140. {
  141.     int phone;
  142.     ipcarg_t method;
  143.     ipcarg_t service;
  144.     int retval;
  145.     static proto_t proto_unknown = { .name = "unknown" };
  146.     proto_t *proto;
  147.     int cphone;
  148.  
  149. //  printf("parse_answer\n");
  150.  
  151.     phone = pcall->phone_hash;
  152.     method = IPC_GET_METHOD(pcall->question);
  153.     retval = IPC_GET_RETVAL(*answer);
  154.     printf("phone=%d, method=%d, retval=%d\n",
  155.         phone, method, retval);
  156.  
  157.     if (phone == 0 && method == IPC_M_CONNECT_ME_TO && retval == 0) {
  158.         /* Connected to a service (through NS) */
  159.         service = IPC_GET_ARG1(pcall->question);
  160.         proto = proto_get_by_srv(service);
  161.         if (proto == NULL) proto = &proto_unknown;
  162.  
  163.         cphone = IPC_GET_ARG5(*answer);
  164.         printf("registering connection (phone %d, protocol: %s)\n", cphone,
  165.             proto->name);
  166.         connection_set(cphone, 0, proto);
  167.     }
  168. }
  169.  
  170. void ipcp_call_in(ipc_call_t *call, ipc_callid_t hash)
  171. {
  172.     link_t *item;
  173.     pending_call_t *pcall;
  174.  
  175. //  printf("ipcp_call_in()\n");
  176. /*  printf("phone: %d, method: ", call->in_phone_hash);
  177.     ipc_m_print(IPC_GET_METHOD(*call));
  178.     printf(" args: (%u, %u, %u, %u, %u)\n",
  179.         IPC_GET_ARG1(*call),
  180.         IPC_GET_ARG2(*call),
  181.         IPC_GET_ARG3(*call),
  182.         IPC_GET_ARG4(*call),
  183.         IPC_GET_ARG5(*call)
  184.     );*/
  185.  
  186.     if ((hash & IPC_CALLID_ANSWERED) == 0 && hash != IPCP_CALLID_SYNC) {
  187.         /* Not a response */
  188.         printf("Not a response (hash %d)\n", hash);
  189.         return;
  190.     }
  191.  
  192.     hash = hash & ~IPC_CALLID_ANSWERED;
  193.  
  194.     item = hash_table_find(&pending_calls, &hash);
  195.     if (item == NULL) return; // No matching question found
  196.    
  197.     pcall = hash_table_get_instance(item, pending_call_t, link);
  198.  
  199.     printf("response matched to question\n");
  200.     hash_table_remove(&pending_calls, &hash, 1);
  201.  
  202.     parse_answer(pcall, call);
  203.     free(pcall);
  204. }
  205.  
  206. void ipcp_call_sync(int phone, ipc_call_t *call, ipc_call_t *answer)
  207. {
  208.     ipcp_call_out(phone, call, IPCP_CALLID_SYNC);
  209.     ipcp_call_in(answer, IPCP_CALLID_SYNC);
  210. }
  211.  
  212. void ipcp_hangup(int phone, int rc)
  213. {
  214.     printf("hangup phone %d -> %d\n", phone, rc);
  215.     connection_clear(phone);
  216. }
  217.  
  218. /** @}
  219.  */
  220.