+
+/**
+ * gras_trp_socket_new:
+ *
+ * Malloc a new socket, and initialize it with defaults
+ */
+void gras_trp_socket_new(int incoming, gras_socket_t * dst)
+{
+
+ gras_socket_t sock = xbt_new0(s_gras_socket_t, 1);
+
+ VERB1("Create a new socket (%p)", (void *) sock);
+
+ sock->plugin = NULL;
+
+ sock->incoming = incoming ? 1 : 0;
+ sock->outgoing = incoming ? 0 : 1;
+ sock->accepting = incoming ? 1 : 0;
+ sock->meas = 0;
+ sock->recvd = 0;
+ sock->valid = 1;
+ sock->moredata = 0;
+
+ sock->sd = -1;
+ sock->port = -1;
+ sock->peer_port = -1;
+ sock->peer_name = NULL;
+ sock->peer_proc = NULL;
+
+ sock->data = NULL;
+ sock->bufdata = NULL;
+
+ *dst = sock;
+
+ XBT_OUT;
+}
+
+/**
+ * @brief Opens a server socket and makes it ready to be listened to.
+ * @param port: port on which you want to listen
+ * @param buf_size: size of the buffer (in byte) on the socket (for TCP sockets only). If 0, a sain default is used (32k, but may change)
+ * @param measurement: whether this socket is meant to convey measurement (if you don't know, use 0 to exchange regular messages)
+ *
+ * In real life, you'll get a TCP socket.
+ */
+gras_socket_t
+gras_socket_server_ext(unsigned short port,
+ unsigned long int buf_size, int measurement)
+{
+
+ xbt_ex_t e;
+ gras_trp_plugin_t trp;
+ gras_socket_t sock;
+
+ DEBUG2("Create a server socket from plugin %s on port %d",
+ gras_if_RL()? "tcp" : "sg", port);
+ trp = gras_trp_plugin_get_by_name(gras_if_SG()? "sg" : "tcp");
+
+ /* defaults settings */
+ gras_trp_socket_new(1, &sock);
+ sock->plugin = trp;
+ sock->port = port;
+ sock->buf_size = buf_size > 0 ? buf_size : 32 * 1024;
+ sock->meas = measurement;
+
+ /* Call plugin socket creation function */
+ DEBUG1("Prepare socket with plugin (fct=%p)", trp->socket_server);
+ TRY {
+ trp->socket_server(trp, sock);
+ DEBUG3("in=%c out=%c accept=%c",
+ sock->incoming ? 'y' : 'n',
+ sock->outgoing ? 'y' : 'n', sock->accepting ? 'y' : 'n');
+ } CATCH(e) {
+
+ free(sock);
+ RETHROW;
+ }
+
+ if (!measurement)
+ ((gras_trp_procdata_t) gras_libdata_by_id(gras_trp_libdata_id))->myport =
+ port;
+ xbt_dynar_push(((gras_trp_procdata_t)
+ gras_libdata_by_id(gras_trp_libdata_id))->sockets, &sock);
+
+ gras_msg_listener_awake();
+ return sock;
+}
+
+/**
+ * @brief Opens a server socket on any port in the given range
+ *
+ * @param minport: first port we will try
+ * @param maxport: last port we will try
+ * @param buf_size: size of the buffer (in byte) on the socket (for TCP sockets only). If 0, a sain default is used (32k, but may change)
+ * @param measurement: whether this socket is meant to convey measurement (if you don't know, use 0 to exchange regular messages)
+ *
+ * If none of the provided ports works, raises the exception got when trying the last possibility
+ */
+gras_socket_t
+gras_socket_server_range(unsigned short minport, unsigned short maxport,
+ unsigned long int buf_size, int measurement)
+{
+
+ int port;
+ gras_socket_t res = NULL;
+ xbt_ex_t e;
+
+ for (port = minport; port < maxport; port++) {
+ TRY {
+ res = gras_socket_server_ext(port, buf_size, measurement);
+ }
+ CATCH(e) {
+ if (port == maxport)
+ RETHROW;
+ xbt_ex_free(e);
+ }
+ if (res)
+ return res;
+ }
+ THROW_IMPOSSIBLE;
+}
+
+/**
+ * @brief Opens a client socket to a remote host.
+ * @param host: who you want to connect to
+ * @param port: where you want to connect to on this host
+ * @param buf_size: size of the buffer (in bytes) on the socket (for TCP sockets only). If 0, a sain default is used (32k, but may change)
+ * @param measurement: whether this socket is meant to convey measurement (if you don't know, use 0 to exchange regular messages)
+ *
+ * In real life, you'll get a TCP socket.
+ */
+gras_socket_t
+gras_socket_client_ext(const char *host,
+ unsigned short port,
+ unsigned long int buf_size, int measurement)
+{
+
+ xbt_ex_t e;
+ gras_trp_plugin_t trp;
+ gras_socket_t sock;
+
+ trp = gras_trp_plugin_get_by_name(gras_if_SG()? "sg" : "tcp");
+
+ DEBUG1("Create a client socket from plugin %s", gras_if_RL()? "tcp" : "sg");
+ /* defaults settings */
+ gras_trp_socket_new(0, &sock);
+ sock->plugin = trp;
+ sock->peer_port = port;
+ sock->peer_name = (char *) strdup(host ? host : "localhost");
+ sock->buf_size = buf_size > 0 ? buf_size : 32 * 1024;
+ sock->meas = measurement;
+
+ /* plugin-specific */
+ TRY {
+ (*trp->socket_client) (trp, sock);
+ DEBUG3("in=%c out=%c accept=%c",
+ sock->incoming ? 'y' : 'n',
+ sock->outgoing ? 'y' : 'n', sock->accepting ? 'y' : 'n');
+ } CATCH(e) {
+ free(sock);
+ RETHROW;
+ }
+ xbt_dynar_push(((gras_trp_procdata_t)
+ gras_libdata_by_id(gras_trp_libdata_id))->sockets, &sock);
+ gras_msg_listener_awake();
+ return sock;
+}
+
+/**
+ * @brief Opens a server socket and make it ready to be listened to.
+ *
+ * In real life, you'll get a TCP socket.
+ */
+gras_socket_t gras_socket_server(unsigned short port)
+{
+ return gras_socket_server_ext(port, 32 * 1024, 0);
+}
+
+/** @brief Opens a client socket to a remote host */
+gras_socket_t gras_socket_client(const char *host, unsigned short port)
+{
+ return gras_socket_client_ext(host, port, 0, 0);
+}
+
+/** @brief Opens a client socket to a remote host specified as '\a host:\a port' */
+gras_socket_t gras_socket_client_from_string(const char *host)
+{
+ xbt_peer_t p = xbt_peer_from_string(host);
+ gras_socket_t res = gras_socket_client_ext(p->name, p->port, 0, 0);
+ xbt_peer_free(p);
+ return res;
+}
+
+void gras_socket_close_voidp(void *sock) {
+ gras_socket_close((gras_socket_t)sock);
+}
+
+/** \brief Close socket */
+void gras_socket_close(gras_socket_t sock)
+{
+ xbt_dynar_t sockets =
+ ((gras_trp_procdata_t) gras_libdata_by_id(gras_trp_libdata_id))->sockets;
+ gras_socket_t sock_iter = NULL;
+ unsigned int cursor;
+
+ XBT_IN;
+ VERB1("Close %p", sock);
+ if (sock == _gras_lastly_selected_socket) {
+ xbt_assert0(!gras_opt_trp_nomoredata_on_close || !sock->moredata,
+ "Closing a socket having more data in buffer while the nomoredata_on_close option is activated");
+
+ if (sock->moredata)
+ CRITICAL0
+ ("Closing a socket having more data in buffer. Option nomoredata_on_close disabled, so continuing.");
+ _gras_lastly_selected_socket = NULL;
+ }