po_hi_driver_sockets_common.c 7.18 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
/*
 * This is a part of PolyORB-HI-C distribution, a minimal
 * middleware written for generated code from AADL models.
 * You should use it with the Ocarina toolsuite.
 *
 * For more informations, please visit http://ocarina.enst.fr
 *
 * Copyright (C) 2010, European Space Agency
 */

#include <deployment.h>

julien.delange's avatar
julien.delange committed
13
14
15
#if (defined (__PO_HI_NEED_DRIVER_SOCKETS) || \
     defined (__PO_HI_NEED_DRIVER_SOCKETS_ASN1) || \
     defined (__PO_HI_NEED_DRIVER_RTEMS_NE2000_SOCKETS))
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

#include <activity.h>

#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>


#include <po_hi_debug.h>
32
#include <po_hi_transport.h>
julien.delange's avatar
julien.delange committed
33
#include <po_hi_main.h>
34
35
36
37
38
39
#include <po_hi_time.h>
#include <po_hi_task.h>
#include <drivers/po_hi_driver_sockets_asn1.h>
#include <drivers/po_hi_driver_sockets_common.h>
#include <drivers/po_hi_driver_sockets.h>

40
#ifdef __PO_HI_NEED_DRIVER_SOCKETS
41
42
__po_hi_inetnode_t nodes[__PO_HI_NB_NODES];
__po_hi_inetnode_t rnodes[__PO_HI_NB_NODES];
43
44
45
46
#else
__po_hi_inetnode_t nodes[__PO_HI_NB_DEVICES];
__po_hi_inetnode_t rnodes[__PO_HI_NB_DEVICES];
#endif
47

julien.delange's avatar
julien.delange committed
48
__po_hi_device_id socket_device_id;
49

julien.delange's avatar
julien.delange committed
50
51
52
#if (defined (__PO_HI_NEED_DRIVER_SOCKETS_ASN1) || \
     defined (__PO_HI_NEED_DRIVER_RTEMS_NE2000_SOCKETS))
void __po_hi_driver_sockets_common_generic_init (__po_hi_device_id id, void* (*poller)(void))
53
54
55
56
57
{
   int                i;
   int                ret;
   int                reuse;
   char               *tmp;
58
   __po_hi_uint16_t   dev;
59
60
61
62
   __po_hi_time_t     mytime;
   struct sockaddr_in sa;
   struct hostent*    hostinfo;

63
64
65
66
   char* dev_conf;
   char dev_addr[16];
   int  dev_port;
   int node;
67

julien.delange's avatar
julien.delange committed
68
   socket_device_id = id;
69
70
71
72

   memset (dev_addr, '\0', 16);

   for (node = 0 ; node < __PO_HI_NB_DEVICES ; node++)
73
74
75
76
77
   {
      nodes[node].socket = -1;
   }


78
79
80
   dev_conf = __po_hi_get_device_naming (id);
   dev_port = 0;

81
   if (sscanf (dev_conf, "ip %s %d", dev_addr, &dev_port) == 0)
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
   {
      __DEBUGMSG ("[DRIVER SOCKETS] Unable to parse device configuration (id=%d)\n", id);
   }

   __DEBUGMSG ("My configuration, addr=%s, port=%d\n", dev_addr, dev_port);

   /*
    * If the current node port has a port number, then it has to
    * listen to other nodes. So, we create a socket, bind it and
    * listen to other nodes.
    */
   if (dev_port != 0)
   {
      nodes[id].socket = socket (AF_INET, SOCK_STREAM, 0);

      if (nodes[id].socket == -1 )
      {
#ifdef __PO_HI_DEBUG
         __DEBUGMSG ("Cannot create socket for device %d\n", id);
#endif
         return;
      }

      reuse = 1;
      setsockopt (nodes[id].socket, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof (reuse));

      sa.sin_addr.s_addr = htonl (INADDR_ANY);   /* We listen on all adresses */
      sa.sin_family = AF_INET;                   
      sa.sin_port = htons (dev_port);   /* Port provided by the generated code */

      if( bind( nodes[id].socket , ( struct sockaddr * ) &sa , sizeof( struct sockaddr_in ) ) < 0 )
      {
#ifdef __PO_HI_DEBUG
         __DEBUGMSG ("Unable to bind socket and port on socket %d\n", nodes[id].socket);
#endif
      }

      if( listen( nodes[id].socket , __PO_HI_NB_ENTITIES ) < 0 )
      {
#ifdef __PO_HI_DEBUG
122
         __DEBUGMSG ("Cannot listen on socket %d\n", nodes[id].socket);
123
124
125
126
127
128
129
130
131
132
133
134
#endif
      }

      /* 
       * Create the thread which receive all data from other
       * nodes. This thread will execute the function
       * __po_hi_receiver_task
       */

      __po_hi_initialize_add_task ();

      __po_hi_create_generic_task 
julien.delange's avatar
julien.delange committed
135
         (-1, 0,__PO_HI_MAX_PRIORITY, 0, poller);
136
137
138
139
140
141
142
143
144
145
146
147
148
   }

   /*
    * For each node in the sytem that may communicate with the current
    * node we create a socket. This socket will be used to send data.
    */
   for (dev = 0 ; dev < __PO_HI_NB_DEVICES ; dev++ )
   {
      if (dev == id)
      {
         continue;
      }

julien.delange's avatar
julien.delange committed
149
150
      __DEBUGMSG ("[DRIVER SOCKETS] Will initialize connection with device %d\n", dev);

151
152
153
154
155
      memset (dev_addr, '\0', 16);
      dev_port = 0;

      dev_conf = __po_hi_get_device_naming (dev);

156
      if (sscanf (dev_conf, "ip %s %d", dev_addr, &dev_port) == 0)
157
158
159
160
161
162
163
164
165
      {
         __DEBUGMSG ("[DRIVER SOCKETS] Unable to parse device configuration (id=%d)\n", id);
         continue;
      }

      __DEBUGMSG ("[DRIVER SOCKETS] Configuration for device %d, addr=%s, port=%d\n", dev, dev_addr, dev_port);

      if (dev_port == 0)
      {
julien.delange's avatar
julien.delange committed
166
         __DEBUGMSG ("[DRIVER SOCKETS] Invalid remote port\n");
167
168
169
170
171
172
173
174
175
         continue;
      }

      while (1)
      {
         nodes[dev].socket = socket (AF_INET, SOCK_STREAM, 0);

         if (nodes[dev].socket == -1 )
         {
176
            __DEBUGMSG ("[DRIVER SOCKETS] Socket for dev %d is not created\n", dev);
177
178
179
            return;
         }

180
181
         __DEBUGMSG ("[DRIVER SOCKETS] Socket for dev %d created, value=%d\n", dev, nodes[dev].socket);

182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
         hostinfo = gethostbyname ((char*)dev_addr);

         if (hostinfo == NULL )
         {
            __DEBUGMSG ("[DRIVER SOCKETS] Error while getting host informations for device %d\n", dev);
         }

         sa.sin_port = htons (dev_port);
         sa.sin_family = AF_INET;

         /* The following lines are used to copy the
          * hostinfo->h_length to the sa.sin_addr member. Most
          * of program use the memcpy to do that, but the
          * RT-POSIX profile we use forbid the use of this
          * function.  We use a loop instead to perform the
          * copy.  So, these lines replace the code :
          *
          * memcpy( (char*) &( sa.sin_addr ) , (char*)hostinfo->h_addr , hostinfo->h_length );
          */

         tmp = (char*) &(sa.sin_addr);
         for (i=0 ; i<hostinfo->h_length ; i++)
         {
            tmp[i] = hostinfo->h_addr[i];
         }

         /*
          * We try to connect on the remote host. We try every
          * second to connect on.
          */
212
         __PO_HI_SET_SOCKET_TIMEOUT(nodes[dev].socket,5);
213
214
215
216
217
218
219
220
221
222
223
224
225

         ret = connect (nodes[dev].socket, 
                        (struct sockaddr*) &sa ,
                        sizeof (struct sockaddr_in));

         if (ret == 0)
         {

            __DEBUGMSG ("[DRIVER SOCKETS] Send my id (%d)\n", id);
            if (write (nodes[dev].socket, &id, sizeof (__po_hi_device_id)) != sizeof (__po_hi_device_id))
            {
               __DEBUGMSG ("[DRIVER SOCKETS] Device %d cannot send his id\n", id);
            }
226
            __DEBUGMSG ("[DRIVER SOCKETS] Connection established with device %d\n", id);
227
228
            break;
         }
229
230
231
232
         else
         {
            __DEBUGMSG ("connect() failed, return=%d\n", ret);
         }
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249

         if (close (nodes[dev].socket))
         {
            __DEBUGMSG ("[DRIVER SOCKETS] Cannot close socket %d\n", nodes[dev].socket);
         }

         /*
          * We wait 500ms each time we try to connect on the
          * remote host
          */

         __po_hi_get_time (&mytime);
         __DEBUGMSG ("[DRIVER SOCKETS] Cannot connect on device %d, wait 500ms\n", dev);
         __po_hi_delay_until (__po_hi_add_times (mytime, __po_hi_milliseconds (500)));
      }
   }
}
250
251
252
#endif


julien.delange's avatar
julien.delange committed
253
254
255
256
#endif /* __PO_HI_NEED_DRIVER_SOCKETS || 
        * __PO_HI_NEED_DRIVER_SOCKETS_ASN1 ||
        * __PO_HI_NEED_DRIVER_RTEMS_ND2000
        */
257