Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Handle the fact that the RL plugin do not exist in SG mode (and vice versa); plugin...
[simgrid.git] / src / gras / Transport / transport.c
1 /* $Id$ */
2
3 /* transport - low level communication                                      */
4
5 /* Authors: Martin Quinson                                                  */
6 /* Copyright (C) 2004 Martin Quinson.                                       */
7
8 /* This program is free software; you can redistribute it and/or modify it
9    under the terms of the license (GNU LGPL) which comes with this package. */
10
11 #include <time.h>       /* time() */
12
13 #include "Transport/transport_private.h"
14
15 GRAS_LOG_NEW_DEFAULT_SUBCATEGORY(transport,GRAS);
16
17 static gras_dict_t  *_gras_trp_plugins;     /* All registered plugins */
18 static void gras_trp_plugin_free(void *p); /* free one of the plugins */
19
20
21 gras_dynar_t *_gras_trp_sockets; /* all existing sockets */
22 static void gras_trp_socket_free(void *s); /* free one socket */
23
24 static fd_set FDread;
25
26 gras_error_t
27 gras_trp_plugin_new(const char *name, gras_trp_setup_t setup);
28
29 gras_error_t
30 gras_trp_plugin_new(const char *name, gras_trp_setup_t setup) {
31   gras_error_t errcode;
32
33   gras_trp_plugin_t *plug = malloc(sizeof(gras_trp_plugin_t));
34   
35   DEBUG1("Create plugin %s",name);
36
37   if (!plug) 
38     RAISE_MALLOC;
39
40   memset(plug,0,sizeof(gras_trp_plugin_t));
41
42   plug->name=strdup(name);
43   if (!plug->name)
44     RAISE_MALLOC;
45
46   errcode = setup(plug);
47   switch (setup(plug)) {
48   case mismatch_error:
49     /* SG plugin return mismatch when in RL mode (and vice versa) */
50     free(plug);
51     break;
52
53   case no_error:
54     TRY(gras_dict_set(_gras_trp_plugins, 
55                       name, plug, gras_trp_plugin_free));
56     break;
57
58   default:
59     free(plug);
60     return errcode;
61   }
62   return no_error;
63 }
64
65 gras_error_t 
66 gras_trp_init(void){
67   gras_error_t errcode;
68   
69   /* make room for all socket ownership descriptions */
70   TRY(gras_dynar_new(&_gras_trp_sockets, sizeof(gras_socket_t*), NULL));
71
72   /* We do not ear for any socket for now */
73   FD_ZERO(&FDread);
74   
75   /* make room for all plugins */
76   TRY(gras_dict_new(&_gras_trp_plugins));
77
78   /* Add them */
79   TRY(gras_trp_plugin_new("tcp", gras_trp_tcp_setup));
80   TRY(gras_trp_plugin_new("file",gras_trp_file_setup));
81   TRY(gras_trp_plugin_new("sg",gras_trp_sg_setup));
82
83   return no_error;
84 }
85
86 void
87 gras_trp_exit(void){
88   gras_dict_free(&_gras_trp_plugins);
89   gras_dynar_free(_gras_trp_sockets);
90 }
91
92
93 void gras_trp_plugin_free(void *p) {
94   gras_trp_plugin_t *plug = p;
95
96   if (plug) {
97     if (plug->exit)
98       plug->exit(plug);
99     else if (plug->data) 
100       free(plug->data);
101
102     free(plug->name);
103     free(plug);
104   }
105 }
106
107
108 /**
109  * gras_trp_socket_new:
110  *
111  * Malloc a new socket, and initialize it with defaults
112  */
113 gras_error_t gras_trp_socket_new(int incoming,
114                                  gras_socket_t **dst) {
115
116   gras_socket_t *sock;
117
118   if (! (sock=malloc(sizeof(gras_socket_t))) )
119     RAISE_MALLOC;
120
121   sock->plugin = NULL;
122   sock->sd     = -1;
123
124   sock->incoming  = incoming ? 1:0;
125   sock->outgoing  = incoming ? 0:1;
126   sock->accepting = incoming ? 1:0;
127
128   sock->port      = -1;
129   sock->peer_port = -1;
130   sock->peer_name = NULL;
131   sock->raw = 0;
132
133   *dst = sock;
134   return no_error;
135 }
136
137
138 /**
139  * gras_socket_server:
140  *
141  * Opens a server socket and make it ready to be listened to.
142  * In real life, you'll get a TCP socket.
143  */
144 gras_error_t
145 gras_socket_server(unsigned short port,
146                    /* OUT */ gras_socket_t **dst) {
147  
148   gras_error_t errcode;
149   gras_trp_plugin_t *trp;
150   gras_socket_t *sock;
151
152   *dst = NULL;
153
154   DEBUG1("Create a server socket from plugin %s",gras_if_RL() ? "tcp" : "sg");
155   TRY(gras_trp_plugin_get_by_name(gras_if_RL() ? "tcp" : "sg",
156                                   &trp));
157
158   /* defaults settings */
159   TRY(gras_trp_socket_new(1,&sock));
160   sock->plugin= trp;
161   sock->port=port;
162
163   /* Call plugin socket creation function */
164   errcode = trp->socket_server(trp, port, sock);
165   DEBUG3("in=%c out=%c accept=%c",
166          sock->incoming?'y':'n', 
167          sock->outgoing?'y':'n',
168          sock->accepting?'y':'n');
169
170   if (errcode != no_error) {
171     free(sock);
172     return errcode;
173   }
174
175   *dst = sock;
176   /* Register this socket */
177   errcode = gras_dynar_push(_gras_trp_sockets,dst);
178   if (errcode != no_error) {
179     free(sock);
180     *dst = NULL;
181     return errcode;
182   }
183
184   return no_error;
185 }
186
187 /**
188  * gras_socket_client:
189  *
190  * Opens a client socket to a remote host.
191  * In real life, you'll get a TCP socket.
192  */
193 gras_error_t
194 gras_socket_client(const char *host,
195                    unsigned short port,
196                    /* OUT */ gras_socket_t **dst) {
197  
198   gras_error_t errcode;
199   gras_trp_plugin_t *trp;
200   gras_socket_t *sock;
201
202   *dst = NULL;
203
204   TRY(gras_trp_plugin_get_by_name(gras_if_RL() ? "tcp" : "sg",
205                                   &trp));
206
207   /* defaults settings */
208   TRY(gras_trp_socket_new(0,&sock));
209   sock->plugin= trp;
210   sock->peer_port = port;
211   sock->peer_name = strdup(host?host:"localhost");
212
213   /* plugin-specific */
214   errcode= (* trp->socket_client)(trp, 
215                                   host ? host : "localhost", port,
216                                   sock);
217   DEBUG3("in=%c out=%c accept=%c",
218          sock->incoming?'y':'n', 
219          sock->outgoing?'y':'n',
220          sock->accepting?'y':'n');
221
222   if (errcode != no_error) {
223     free(sock);
224     return errcode;
225   }
226
227   /* register socket */
228   *dst = sock;
229   errcode = gras_dynar_push(_gras_trp_sockets,dst);
230   if (errcode != no_error) {
231     free(sock);
232     *dst = NULL;
233     return errcode;
234   }
235
236   return no_error;
237 }
238
239 void gras_socket_close(gras_socket_t **sock) {
240   gras_socket_t *sock_iter;
241   int cursor;
242
243   /* FIXME: Issue an event when the socket is closed */
244   if (sock && *sock) {
245     gras_dynar_foreach(_gras_trp_sockets,cursor,sock_iter) {
246       if (*sock == sock_iter) {
247         gras_dynar_cursor_rm(_gras_trp_sockets,&cursor);
248         if ( (*sock)->plugin->socket_close) 
249           (* (*sock)->plugin->socket_close)(*sock);
250
251         /* free the memory */
252         free(*sock);
253         *sock=NULL;
254         return;
255       }
256     }
257     WARN0("Ignoring request to free an unknown socket");
258   }
259 }
260
261 /**
262  * gras_trp_chunk_send:
263  *
264  * Send a bunch of bytes from on socket
265  */
266 gras_error_t
267 gras_trp_chunk_send(gras_socket_t *sd,
268                     char *data,
269                     size_t size) {
270   gras_assert1(sd->outgoing,
271                "Socket not suited for data send (outgoing=%c)",
272                sd->outgoing?'y':'n');
273   gras_assert1(sd->plugin->chunk_send,
274                "No function chunk_send on transport plugin %s",
275                sd->plugin->name);
276   return (*sd->plugin->chunk_send)(sd,data,size);
277 }
278 /**
279  * gras_trp_chunk_recv:
280  *
281  * Receive a bunch of bytes from a socket
282  */
283 gras_error_t 
284 gras_trp_chunk_recv(gras_socket_t *sd,
285                     char *data,
286                     size_t size) {
287   gras_assert0(sd->incoming,
288                "Socket not suited for data receive");
289   gras_assert1(sd->plugin->chunk_recv,
290                "No function chunk_recv on transport plugin %s",
291                sd->plugin->name);
292   return (sd->plugin->chunk_recv)(sd,data,size);
293 }
294
295
296 gras_error_t
297 gras_trp_plugin_get_by_name(const char *name,
298                             gras_trp_plugin_t **dst){
299
300   return gras_dict_get(_gras_trp_plugins,name,(void**)dst);
301 }
302
303 int   gras_socket_my_port  (gras_socket_t *sock) {
304   return sock->port;
305 }
306 int   gras_socket_peer_port(gras_socket_t *sock) {
307   return sock->peer_port;
308 }
309 char *gras_socket_peer_name(gras_socket_t *sock) {
310   return sock->peer_name;
311 }