Subversion Repositories HelenOS

Rev

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