PageRenderTime 389ms CodeModel.GetById 274ms app.highlight 105ms RepoModel.GetById 1ms app.codeStats 0ms

/xlators/protocol/legacy/transport/socket/src/socket.c

https://github.com/dopry/glusterfs
C | 1625 lines | 1242 code | 329 blank | 54 comment | 232 complexity | fcb24a73f68c2a2e6e846c0ade11f687 MD5 | raw file
   1/*
   2  Copyright (c) 2008-2011 Gluster, Inc. <http://www.gluster.com>
   3  This file is part of GlusterFS.
   4
   5  GlusterFS is free software; you can redistribute it and/or modify
   6  it under the terms of the GNU General Public License as published
   7  by the Free Software Foundation; either version 3 of the License,
   8  or (at your option) any later version.
   9
  10  GlusterFS is distributed in the hope that it will be useful, but
  11  WITHOUT ANY WARRANTY; without even the implied warranty of
  12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13  General Public License for more details.
  14
  15  You should have received a copy of the GNU General Public License
  16  along with this program.  If not, see
  17  <http://www.gnu.org/licenses/>.
  18*/
  19
  20
  21#ifndef _CONFIG_H
  22#define _CONFIG_H
  23#include "config.h"
  24#endif
  25
  26#include "socket.h"
  27#include "name.h"
  28#include "dict.h"
  29#include "transport.h"
  30#include "logging.h"
  31#include "xlator.h"
  32#include "byte-order.h"
  33#include "common-utils.h"
  34#include "compat-errno.h"
  35
  36#include <fcntl.h>
  37#include <errno.h>
  38#include <netinet/tcp.h>
  39
  40
  41#define GF_LOG_ERRNO(errno) ((errno == ENOTCONN) ? GF_LOG_DEBUG : GF_LOG_ERROR)
  42#define SA(ptr) ((struct sockaddr *)ptr)
  43
  44static int socket_init (transport_t *this);
  45
  46/*
  47 * return value:
  48 *   0 = success (completed)
  49 *  -1 = error
  50 * > 0 = incomplete
  51 */
  52
  53static int
  54__socket_rwv (transport_t *this, struct iovec *vector, int count,
  55              struct iovec **pending_vector, int *pending_count,
  56              int write)
  57{
  58        socket_private_t *priv = NULL;
  59        int               sock = -1;
  60        int               ret = -1;
  61        struct iovec     *opvector = NULL;
  62        int               opcount = 0;
  63        int               moved = 0;
  64
  65        priv = this->private;
  66        sock = priv->sock;
  67
  68	opvector = vector;
  69	opcount  = count;
  70
  71        while (opcount) {
  72                if (write) {
  73                        ret = writev (sock, opvector, opcount);
  74
  75                        if (ret == 0 || (ret == -1 && errno == EAGAIN)) {
  76                                /* done for now */
  77                                break;
  78                        }
  79                } else {
  80                        ret = readv (sock, opvector, opcount);
  81
  82                        if (ret == -1 && errno == EAGAIN) {
  83                                /* done for now */
  84                                break;
  85                        }
  86                }
  87
  88                if (ret == 0) {
  89                        /* Mostly due to 'umount' in client */
  90                        gf_log (this->xl->name, GF_LOG_TRACE,
  91                                "EOF from peer %s", this->peerinfo.identifier);
  92                        opcount = -1;
  93                        errno = ENOTCONN;
  94                        break;
  95                }
  96
  97                if (ret == -1) {
  98                        if (errno == EINTR)
  99                                continue;
 100
 101                        gf_log (this->xl->name, GF_LOG_TRACE,
 102                                "%s failed (%s)", write ? "writev" : "readv",
 103                                strerror (errno));
 104                        opcount = -1;
 105                        break;
 106                }
 107
 108                moved = 0;
 109
 110                while (moved < ret) {
 111                        if ((ret - moved) >= opvector[0].iov_len) {
 112                                moved += opvector[0].iov_len;
 113                                opvector++;
 114                                opcount--;
 115                        } else {
 116                                opvector[0].iov_len -= (ret - moved);
 117                                opvector[0].iov_base += (ret - moved);
 118                                moved += (ret - moved);
 119                        }
 120                        while (opcount && !opvector[0].iov_len) {
 121                                opvector++;
 122                                opcount--;
 123                        }
 124                }
 125        }
 126
 127        if (pending_vector)
 128                *pending_vector = opvector;
 129
 130        if (pending_count)
 131                *pending_count = opcount;
 132
 133        return opcount;
 134}
 135
 136
 137static int
 138__socket_readv (transport_t *this, struct iovec *vector, int count,
 139                struct iovec **pending_vector, int *pending_count)
 140{
 141        int ret = -1;
 142
 143        ret = __socket_rwv (this, vector, count,
 144			    pending_vector, pending_count, 0);
 145
 146        return ret;
 147}
 148
 149
 150static int
 151__socket_writev (transport_t *this, struct iovec *vector, int count,
 152                 struct iovec **pending_vector, int *pending_count)
 153{
 154        int ret = -1;
 155
 156        ret = __socket_rwv (this, vector, count,
 157			    pending_vector, pending_count, 1);
 158
 159        return ret;
 160}
 161
 162
 163static int
 164__socket_disconnect (transport_t *this)
 165{
 166        socket_private_t *priv = NULL;
 167        int               ret = -1;
 168
 169        priv = this->private;
 170
 171        if (priv->sock != -1) {
 172                ret = shutdown (priv->sock, SHUT_RDWR);
 173                priv->connected = -1;
 174                gf_log (this->xl->name, GF_LOG_TRACE,
 175                        "shutdown() returned %d. set connection state to -1",
 176                        ret);
 177        }
 178
 179        return ret;
 180}
 181
 182
 183static int
 184__socket_server_bind (transport_t *this)
 185{
 186        socket_private_t *priv = NULL;
 187        int               ret = -1;
 188	int               opt = 1;
 189
 190	priv = this->private;
 191
 192        ret = setsockopt (priv->sock, SOL_SOCKET, SO_REUSEADDR,
 193			  &opt, sizeof (opt));
 194
 195        if (ret == -1) {
 196                gf_log (this->xl->name, GF_LOG_ERROR,
 197                        "setsockopt() for SO_REUSEADDR failed (%s)",
 198                        strerror (errno));
 199        }
 200
 201        ret = bind (priv->sock, (struct sockaddr *)&this->myinfo.sockaddr,
 202		    this->myinfo.sockaddr_len);
 203
 204        if (ret == -1) {
 205                gf_log (this->xl->name, GF_LOG_ERROR,
 206                        "binding to %s failed: %s",
 207                        this->myinfo.identifier, strerror (errno));
 208                if (errno == EADDRINUSE) {
 209                        gf_log (this->xl->name, GF_LOG_ERROR, 
 210                                "Port is already in use");
 211                }
 212        }
 213
 214        return ret;
 215}
 216
 217
 218static int
 219__socket_nonblock (int fd)
 220{
 221        int flags = 0;
 222        int ret = -1;
 223
 224        flags = fcntl (fd, F_GETFL);
 225
 226        if (flags != -1)
 227                ret = fcntl (fd, F_SETFL, flags | O_NONBLOCK);
 228
 229        return ret;
 230}
 231
 232
 233static int
 234__socket_nodelay (int fd)
 235{
 236        int     on = 1;
 237        int     ret = -1;
 238
 239        ret = setsockopt (fd, IPPROTO_TCP, TCP_NODELAY,
 240			  &on, sizeof (on));
 241        if (!ret)
 242                gf_log ("", GF_LOG_TRACE,
 243                        "NODELAY enabled for socket %d", fd);
 244
 245        return ret;
 246}
 247
 248
 249static int
 250__socket_keepalive (int fd, int keepalive_intvl)
 251{
 252        int     on = 1;
 253        int     ret = -1;
 254
 255        ret = setsockopt (fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on));
 256        if (ret == -1)
 257                goto err;
 258
 259        if (keepalive_intvl == GF_USE_DEFAULT_KEEPALIVE)
 260                goto done;
 261
 262#ifndef GF_LINUX_HOST_OS
 263        ret = setsockopt (fd, IPPROTO_TCP, TCP_KEEPALIVE, &keepalive_intvl,
 264                          sizeof (keepalive_intvl));
 265        if (ret == -1)
 266                goto err;
 267#else
 268        ret = setsockopt (fd, IPPROTO_TCP, TCP_KEEPIDLE, &keepalive_intvl,
 269                          sizeof (keepalive_intvl));
 270        if (ret == -1)
 271                goto err;
 272
 273        ret = setsockopt (fd, IPPROTO_TCP, TCP_KEEPINTVL, &keepalive_intvl,
 274                          sizeof (keepalive_intvl));
 275        if (ret == -1)
 276                goto err;
 277#endif
 278
 279done:
 280        gf_log ("", GF_LOG_TRACE, "Keep-alive enabled for socket %d, interval "
 281                "%d", fd, keepalive_intvl);
 282
 283err:
 284        return ret;
 285}
 286
 287
 288static int
 289__socket_connect_finish (int fd)
 290{
 291        int       ret = -1;
 292        int       optval = 0;
 293        socklen_t optlen = sizeof (int);
 294
 295        ret = getsockopt (fd, SOL_SOCKET, SO_ERROR, (void *)&optval, &optlen);
 296
 297        if (ret == 0 && optval) {
 298                errno = optval;
 299                ret = -1;
 300        }
 301
 302        return ret;
 303}
 304
 305
 306static void
 307__socket_reset (transport_t *this)
 308{
 309        socket_private_t *priv = NULL;
 310
 311        priv = this->private;
 312
 313        /* TODO: use mem-pool on incoming data */
 314
 315        if (priv->incoming.hdr_p)
 316                GF_FREE (priv->incoming.hdr_p);
 317
 318        if (priv->incoming.iobuf)
 319                iobuf_unref (priv->incoming.iobuf);
 320
 321        memset (&priv->incoming, 0, sizeof (priv->incoming));
 322
 323        event_unregister (this->xl->ctx->event_pool, priv->sock, priv->idx);
 324        close (priv->sock);
 325        priv->sock = -1;
 326        priv->idx = -1;
 327        priv->connected = -1;
 328}
 329
 330
 331static struct ioq *
 332__socket_ioq_new (transport_t *this, char *buf, int len,
 333                  struct iovec *vector, int count, struct iobref *iobref)
 334{
 335        socket_private_t *priv = NULL;
 336        struct ioq       *entry = NULL;
 337
 338        priv = this->private;
 339
 340        /* TODO: use mem-pool */
 341        entry = GF_CALLOC (1, sizeof (*entry),
 342                           gf_common_mt_ioq);
 343        if (!entry)
 344                return NULL;
 345
 346        GF_ASSERT (count <= (MAX_IOVEC-2));
 347
 348        entry->header.colonO[0] = ':';
 349        entry->header.colonO[1] = 'O';
 350        entry->header.colonO[2] = '\0';
 351        entry->header.version   = 42;
 352        entry->header.size1     = hton32 (len);
 353        entry->header.size2     = hton32 (iov_length (vector, count));
 354
 355        entry->vector[0].iov_base = &entry->header;
 356        entry->vector[0].iov_len  = sizeof (entry->header);
 357        entry->count++;
 358
 359        entry->vector[1].iov_base = buf;
 360        entry->vector[1].iov_len  = len;
 361        entry->count++;
 362
 363        if (vector && count) {
 364                memcpy (&entry->vector[2], vector, sizeof (*vector) * count);
 365                entry->count += count;
 366        }
 367
 368        entry->pending_vector = entry->vector;
 369        entry->pending_count  = entry->count;
 370
 371        if (iobref)
 372                entry->iobref = iobref_ref (iobref);
 373
 374        entry->buf = buf;
 375
 376        INIT_LIST_HEAD (&entry->list);
 377
 378        return entry;
 379}
 380
 381
 382static void
 383__socket_ioq_entry_free (struct ioq *entry)
 384{
 385        list_del_init (&entry->list);
 386        if (entry->iobref)
 387                iobref_unref (entry->iobref);
 388
 389        /* TODO: use mem-pool */
 390        GF_FREE (entry->buf);
 391
 392        /* TODO: use mem-pool */
 393        GF_FREE (entry);
 394}
 395
 396
 397static void
 398__socket_ioq_flush (transport_t *this)
 399{
 400        socket_private_t *priv = NULL;
 401        struct ioq       *entry = NULL;
 402
 403        priv = this->private;
 404
 405        while (!list_empty (&priv->ioq)) {
 406                entry = priv->ioq_next;
 407                __socket_ioq_entry_free (entry);
 408        }
 409
 410        return;
 411}
 412
 413
 414static int
 415__socket_ioq_churn_entry (transport_t *this, struct ioq *entry)
 416{
 417        int ret = -1;
 418
 419        ret = __socket_writev (this, entry->pending_vector,
 420			       entry->pending_count,
 421                               &entry->pending_vector,
 422			       &entry->pending_count);
 423
 424        if (ret == 0) {
 425                /* current entry was completely written */
 426                GF_ASSERT (entry->pending_count == 0);
 427                __socket_ioq_entry_free (entry);
 428        }
 429
 430        return ret;
 431}
 432
 433
 434static int
 435__socket_ioq_churn (transport_t *this)
 436{
 437        socket_private_t *priv = NULL;
 438        int               ret = 0;
 439        struct ioq       *entry = NULL;
 440
 441        priv = this->private;
 442
 443        while (!list_empty (&priv->ioq)) {
 444                /* pick next entry */
 445                entry = priv->ioq_next;
 446
 447                ret = __socket_ioq_churn_entry (this, entry);
 448
 449                if (ret != 0)
 450                        break;
 451        }
 452
 453        if (list_empty (&priv->ioq)) {
 454                /* all pending writes done, not interested in POLLOUT */
 455                priv->idx = event_select_on (this->xl->ctx->event_pool,
 456					     priv->sock, priv->idx, -1, 0);
 457        }
 458
 459        return ret;
 460}
 461
 462
 463static int
 464socket_event_poll_err (transport_t *this)
 465{
 466        socket_private_t *priv = NULL;
 467        int               ret = -1;
 468
 469        priv = this->private;
 470
 471        pthread_mutex_lock (&priv->lock);
 472        {
 473                __socket_ioq_flush (this);
 474                __socket_reset (this);
 475        }
 476        pthread_mutex_unlock (&priv->lock);
 477
 478        xlator_notify (this->xl, GF_EVENT_POLLERR, this);
 479
 480        return ret;
 481}
 482
 483
 484static int
 485socket_event_poll_out (transport_t *this)
 486{
 487        socket_private_t *priv = NULL;
 488        int               ret = -1;
 489
 490        priv = this->private;
 491
 492        pthread_mutex_lock (&priv->lock);
 493        {
 494                if (priv->connected == 1) {
 495                        ret = __socket_ioq_churn (this);
 496
 497                        if (ret == -1) {
 498                                __socket_disconnect (this);
 499                        }
 500                }
 501        }
 502        pthread_mutex_unlock (&priv->lock);
 503
 504        xlator_notify (this->xl, GF_EVENT_POLLOUT, this);
 505
 506        return ret;
 507}
 508
 509
 510static int
 511__socket_proto_validate_header (transport_t *this,
 512				struct socket_header *header,
 513				size_t *size1_p, size_t *size2_p)
 514{
 515        size_t size1 = 0;
 516	size_t size2 = 0;
 517
 518        if (strcmp (header->colonO, ":O")) {
 519                gf_log (this->xl->name, GF_LOG_DEBUG,
 520                        "socket header signature does not match :O (%x.%x.%x)",
 521                        header->colonO[0], header->colonO[1],
 522			header->colonO[2]);
 523                return -1;
 524        }
 525
 526        if (header->version != 42) {
 527                gf_log (this->xl->name, GF_LOG_DEBUG,
 528                        "socket header version does not match 42 != %d",
 529			header->version);
 530                return -1;
 531        }
 532
 533        size1 = ntoh32 (header->size1);
 534        size2 = ntoh32 (header->size2);
 535
 536        if (size1 <= 0 || size1 > 1048576) {
 537                gf_log (this->xl->name, GF_LOG_DEBUG,
 538                        "socket header has incorrect size1=%"GF_PRI_SIZET,
 539			size1);
 540                return -1;
 541        }
 542
 543        if (size2 > (131072)) {
 544                gf_log (this->xl->name, GF_LOG_DEBUG,
 545                        "socket header has incorrect size2=%"GF_PRI_SIZET,
 546			size2);
 547                return -1;
 548        }
 549
 550        if (size1_p)
 551                *size1_p = size1;
 552
 553        if (size2_p)
 554                *size2_p = size2;
 555
 556        return 0;
 557}
 558
 559
 560
 561/* socket protocol state machine */
 562
 563static int
 564__socket_proto_state_machine (transport_t *this)
 565{
 566        int                   ret = -1;
 567        socket_private_t     *priv = NULL;
 568        size_t                size1 = 0;
 569	size_t                size2 = 0;
 570        int                   previous_state = -1;
 571	struct socket_header *hdr = NULL;
 572        struct iobuf         *iobuf = NULL;
 573
 574
 575        priv = this->private;
 576
 577	while (priv->incoming.state != SOCKET_PROTO_STATE_COMPLETE) {
 578		/* debug check against infinite loops */
 579		if (previous_state == priv->incoming.state) {
 580			gf_log (this->xl->name, GF_LOG_DEBUG,
 581				"state did not change! (%d) breaking",
 582				previous_state);
 583			ret = -1;
 584			goto unlock;
 585		}
 586		previous_state = priv->incoming.state;
 587
 588		switch (priv->incoming.state) {
 589
 590		case SOCKET_PROTO_STATE_NADA:
 591			priv->incoming.pending_vector =
 592				priv->incoming.vector;
 593
 594			priv->incoming.pending_vector->iov_base =
 595				&priv->incoming.header;
 596
 597			priv->incoming.pending_vector->iov_len  =
 598				sizeof (struct socket_header);
 599
 600			priv->incoming.state =
 601				SOCKET_PROTO_STATE_HEADER_COMING;
 602			break;
 603
 604		case SOCKET_PROTO_STATE_HEADER_COMING:
 605
 606			ret = __socket_readv (this,
 607					      priv->incoming.pending_vector, 1,
 608					      &priv->incoming.pending_vector,
 609					      NULL);
 610			if (ret == 0) {
 611				priv->incoming.state =
 612					SOCKET_PROTO_STATE_HEADER_CAME;
 613				break;
 614			}
 615
 616			if (ret == -1) {
 617				gf_log (this->xl->name, GF_LOG_TRACE,
 618					"read (%s) in state %d (%s)",
 619					strerror (errno),
 620					SOCKET_PROTO_STATE_HEADER_COMING, 
 621					this->peerinfo.identifier);
 622				goto unlock;
 623			}
 624
 625			if (ret > 0) {
 626				gf_log (this->xl->name, GF_LOG_TRACE,
 627					"partial header read on NB socket.");
 628				goto unlock;
 629			}
 630			break;
 631
 632		case SOCKET_PROTO_STATE_HEADER_CAME:
 633			hdr = &priv->incoming.header;
 634			ret = __socket_proto_validate_header (this, hdr,
 635							      &size1, &size2);
 636
 637			if (ret == -1) {
 638				gf_log (this->xl->name, GF_LOG_ERROR,
 639					"socket header validate failed (%s). "
 640					"possible mismatch of transport-type "
 641					"between server and client volumes, "
 642					"or version mismatch",
 643					this->peerinfo.identifier);
 644                                        goto unlock;
 645                        }
 646
 647                        priv->incoming.hdrlen = size1;
 648                        priv->incoming.buflen = size2;
 649
 650                        /* TODO: use mem-pool */
 651                        priv->incoming.hdr_p  = GF_MALLOC (size1, 
 652                                                           gf_common_mt_char);
 653                        if (size2) {
 654                                /* TODO: sanity check size2 < page size
 655                                 */
 656                                iobuf = iobuf_get (this->xl->ctx->iobuf_pool);
 657                                if (!iobuf) {
 658                                        gf_log (this->xl->name, GF_LOG_ERROR,
 659                                                "unable to allocate IO buffer "
 660                                                "for peer %s",
 661                                                this->peerinfo.identifier);
 662                                        ret = -ENOMEM;
 663                                        goto unlock;
 664                                }
 665                                priv->incoming.iobuf = iobuf;
 666                                priv->incoming.buf_p = iobuf->ptr;
 667                        }
 668
 669                        priv->incoming.vector[0].iov_base =
 670                                priv->incoming.hdr_p;
 671
 672                        priv->incoming.vector[0].iov_len  = size1;
 673
 674                        priv->incoming.vector[1].iov_base =
 675                                priv->incoming.buf_p;
 676
 677                        priv->incoming.vector[1].iov_len  = size2;
 678                        priv->incoming.count = size2 ? 2 : 1;
 679
 680                        priv->incoming.pending_vector =
 681                                priv->incoming.vector;
 682
 683                        priv->incoming.pending_count  =
 684                                priv->incoming.count;
 685
 686                        priv->incoming.state =
 687                                SOCKET_PROTO_STATE_DATA_COMING;
 688                        break;
 689
 690		case SOCKET_PROTO_STATE_DATA_COMING:
 691
 692			ret = __socket_readv (this,
 693					      priv->incoming.pending_vector,
 694					      priv->incoming.pending_count,
 695					      &priv->incoming.pending_vector,
 696					      &priv->incoming.pending_count);
 697			if (ret == 0) {
 698				priv->incoming.state =
 699					SOCKET_PROTO_STATE_DATA_CAME;
 700				break;
 701			}
 702
 703			if (ret == -1) {
 704				gf_log (this->xl->name, GF_LOG_DEBUG,
 705					"read (%s) in state %d (%s)",
 706					strerror (errno),
 707					SOCKET_PROTO_STATE_DATA_COMING,
 708					this->peerinfo.identifier);
 709				goto unlock;
 710			}
 711
 712			if (ret > 0) {
 713				gf_log (this->xl->name, GF_LOG_TRACE,
 714					"partial data read on NB socket");
 715                                        goto unlock;
 716			}
 717			break;
 718
 719		case SOCKET_PROTO_STATE_DATA_CAME:
 720			memset (&priv->incoming.vector, 0,
 721				sizeof (priv->incoming.vector));
 722			priv->incoming.pending_vector = NULL;
 723			priv->incoming.pending_count  = 0;
 724			priv->incoming.state = SOCKET_PROTO_STATE_COMPLETE;
 725			break;
 726
 727		case SOCKET_PROTO_STATE_COMPLETE:
 728			/* not reached */
 729			break;
 730
 731		default:
 732			gf_log (this->xl->name, GF_LOG_DEBUG,
 733				"undefined state reached: %d",
 734				priv->incoming.state);
 735                                goto unlock;
 736		}
 737	}
 738unlock:
 739
 740        return ret;
 741}
 742
 743
 744static int
 745socket_proto_state_machine (transport_t *this)
 746{
 747        socket_private_t *priv = NULL;
 748	int               ret = 0;
 749
 750	priv = this->private;
 751
 752	pthread_mutex_lock (&priv->lock);
 753	{
 754		ret = __socket_proto_state_machine (this);
 755	}
 756        pthread_mutex_unlock (&priv->lock);
 757
 758	return ret;
 759}
 760
 761
 762static int
 763socket_event_poll_in (transport_t *this)
 764{
 765        int ret = -1;
 766
 767        ret = socket_proto_state_machine (this);
 768
 769        /* call POLLIN on xlator even if complete block is not received,
 770           just to keep the last_received timestamp ticking */
 771
 772        if (ret == 0)
 773                ret = xlator_notify (this->xl, GF_EVENT_POLLIN, this);
 774
 775        return ret;
 776}
 777
 778
 779static int
 780socket_connect_finish (transport_t *this)
 781{
 782        int               ret = -1;
 783        socket_private_t *priv = NULL;
 784        int               event = -1;
 785        char              notify_xlator = 0;
 786
 787        priv = this->private;
 788
 789        pthread_mutex_lock (&priv->lock);
 790        {
 791		if (priv->connected)
 792			goto unlock;
 793
 794		ret = __socket_connect_finish (priv->sock);
 795
 796		if (ret == -1 && errno == EINPROGRESS)
 797			ret = 1;
 798
 799		if (ret == -1 && errno != EINPROGRESS) {
 800			if (!priv->connect_finish_log) {
 801				gf_log (this->xl->name, GF_LOG_ERROR,
 802					"connection to %s failed (%s)",
 803                                        this->peerinfo.identifier,
 804					strerror (errno));
 805				priv->connect_finish_log = 1;
 806			}
 807			__socket_disconnect (this);
 808			notify_xlator = 1;
 809			event = GF_EVENT_POLLERR;
 810			goto unlock;
 811		}
 812
 813		if (ret == 0) {
 814			notify_xlator = 1;
 815
 816			this->myinfo.sockaddr_len =
 817				sizeof (this->myinfo.sockaddr);
 818
 819			ret = getsockname (priv->sock,
 820					   SA (&this->myinfo.sockaddr),
 821					   &this->myinfo.sockaddr_len);
 822			if (ret == -1) {
 823				gf_log (this->xl->name, GF_LOG_DEBUG,
 824					"getsockname on (%d) failed (%s)", 
 825					priv->sock, strerror (errno));
 826				__socket_disconnect (this);
 827				event = GF_EVENT_POLLERR;
 828				goto unlock;
 829			}
 830
 831			priv->connected = 1;
 832			priv->connect_finish_log = 0;
 833			event = GF_EVENT_CHILD_UP;
 834			gf_get_transport_identifiers (this);
 835		}
 836        }
 837unlock:
 838        pthread_mutex_unlock (&priv->lock);
 839
 840        if (notify_xlator)
 841                xlator_notify (this->xl, event, this);
 842
 843        return 0;
 844}
 845
 846
 847static int
 848socket_event_handler (int fd, int idx, void *data,
 849                      int poll_in, int poll_out, int poll_err)
 850{
 851        transport_t      *this = NULL;
 852        socket_private_t *priv = NULL;
 853        int               ret = 0;
 854
 855        this = data;
 856        priv = this->private;
 857
 858        pthread_mutex_lock (&priv->lock);
 859        {
 860                priv->idx = idx;
 861        }
 862        pthread_mutex_unlock (&priv->lock);
 863
 864        if (!priv->connected) {
 865                ret = socket_connect_finish (this);
 866        }
 867
 868        if (!ret && poll_out) {
 869                ret = socket_event_poll_out (this);
 870        }
 871
 872        if (!ret && poll_in) {
 873                ret = socket_event_poll_in (this);
 874        }
 875
 876        if (ret < 0 || poll_err) {
 877                socket_event_poll_err (this);
 878                transport_unref (this);
 879        }
 880
 881        return 0;
 882}
 883
 884
 885static int
 886socket_server_event_handler (int fd, int idx, void *data,
 887                             int poll_in, int poll_out, int poll_err)
 888{
 889        transport_t             *this = NULL;
 890        socket_private_t        *priv = NULL;
 891        int                      ret = 0;
 892        int                      new_sock = -1;
 893        transport_t             *new_trans = NULL;
 894        struct sockaddr_storage  new_sockaddr = {0, };
 895        socklen_t                addrlen = sizeof (new_sockaddr);
 896        socket_private_t        *new_priv = NULL;
 897	glusterfs_ctx_t         *ctx = NULL;
 898
 899        this = data;
 900        priv = this->private;
 901	ctx  = this->xl->ctx;
 902
 903        pthread_mutex_lock (&priv->lock);
 904        {
 905                priv->idx = idx;
 906
 907                if (poll_in) {
 908                        new_sock = accept (priv->sock, SA (&new_sockaddr),
 909					   &addrlen);
 910
 911                        if (new_sock == -1)
 912                                goto unlock;
 913
 914                        if (!priv->bio) {
 915                                ret = __socket_nonblock (new_sock);
 916
 917                                if (ret == -1) {
 918                                        gf_log (this->xl->name, GF_LOG_DEBUG,
 919                                                "NBIO on %d failed (%s)",
 920                                                new_sock, strerror (errno));
 921                                        close (new_sock);
 922                                        goto unlock;
 923                                }
 924                        }
 925
 926                        if (priv->nodelay) {
 927                                ret = __socket_nodelay (new_sock);
 928                                if (ret == -1) {
 929                                        gf_log (this->xl->name, GF_LOG_ERROR,
 930                                                "setsockopt() failed for "
 931                                                "NODELAY (%s)",
 932                                                strerror (errno));
 933                                }
 934                        }
 935
 936                        if (priv->keepalive) {
 937                                ret = __socket_keepalive (new_sock,
 938                                                          priv->keepaliveintvl);
 939                                if (ret == -1)
 940                                        gf_log (this->xl->name, GF_LOG_ERROR,
 941                                                "Failed to set keep-alive: %s",
 942                                                strerror (errno));
 943                        }
 944
 945                        new_trans = GF_CALLOC (1, sizeof (*new_trans), 
 946                                               gf_common_mt_transport_t);
 947                        new_trans->xl = this->xl;
 948                        new_trans->fini = this->fini;
 949
 950                        memcpy (&new_trans->peerinfo.sockaddr, &new_sockaddr,
 951				addrlen);
 952                        new_trans->peerinfo.sockaddr_len = addrlen;
 953
 954                        new_trans->myinfo.sockaddr_len =
 955				sizeof (new_trans->myinfo.sockaddr);
 956
 957                        ret = getsockname (new_sock, 
 958                                           SA (&new_trans->myinfo.sockaddr),
 959                                           &new_trans->myinfo.sockaddr_len);
 960                        if (ret == -1) {
 961                                gf_log (this->xl->name, GF_LOG_DEBUG,
 962                                        "getsockname on %d failed (%s)", 
 963                                        new_sock, strerror (errno));
 964                                close (new_sock);
 965                                goto unlock;
 966                        }
 967
 968                        gf_get_transport_identifiers (new_trans);
 969                        socket_init (new_trans);
 970                        new_trans->ops = this->ops;
 971                        new_trans->init = this->init;
 972                        new_trans->fini = this->fini;
 973
 974                        new_priv = new_trans->private;
 975
 976                        pthread_mutex_lock (&new_priv->lock);
 977                        {
 978                                new_priv->sock = new_sock;
 979                                new_priv->connected = 1;
 980        
 981                                transport_ref (new_trans);
 982                                new_priv->idx =
 983					event_register (ctx->event_pool,
 984							new_sock,
 985							socket_event_handler,
 986							new_trans, 1, 0);
 987
 988                                if (new_priv->idx == -1)
 989                                        ret = -1;
 990                        }
 991                        pthread_mutex_unlock (&new_priv->lock);
 992                }
 993        }
 994unlock:
 995        pthread_mutex_unlock (&priv->lock);
 996
 997        return ret;
 998}
 999
1000
1001static int
1002socket_disconnect (transport_t *this)
1003{
1004        socket_private_t *priv = NULL;
1005        int               ret = -1;
1006
1007        priv = this->private;
1008
1009        pthread_mutex_lock (&priv->lock);
1010        {
1011                ret = __socket_disconnect (this);
1012        }
1013        pthread_mutex_unlock (&priv->lock);
1014
1015        return ret;
1016}
1017
1018
1019static int
1020socket_connect (transport_t *this)
1021{
1022        int                      ret = -1;
1023	int                      sock = -1;
1024        socket_private_t        *priv = NULL;
1025        struct sockaddr_storage  sockaddr = {0, };
1026        socklen_t                sockaddr_len = 0;
1027	glusterfs_ctx_t         *ctx = NULL;
1028        sa_family_t              sa_family = {0, };
1029
1030        priv = this->private;
1031	ctx = this->xl->ctx;
1032
1033        if (!priv) {
1034                gf_log (this->xl->name, GF_LOG_DEBUG,
1035                        "connect() called on uninitialized transport");
1036                goto err;
1037        }
1038
1039        pthread_mutex_lock (&priv->lock);
1040        {
1041                sock = priv->sock;
1042        }
1043        pthread_mutex_unlock (&priv->lock);
1044
1045        if (sock != -1) {
1046                gf_log (this->xl->name, GF_LOG_TRACE,
1047                        "connect () called on transport already connected");
1048                ret = 0;
1049                goto err;
1050        }
1051
1052        ret = gf_socket_client_get_remote_sockaddr (this, SA (&sockaddr),
1053                                                 &sockaddr_len, &sa_family);
1054        if (ret == -1) {
1055                /* logged inside client_get_remote_sockaddr */
1056                goto err;
1057        }
1058
1059        pthread_mutex_lock (&priv->lock);
1060        {
1061                if (priv->sock != -1) {
1062                        gf_log (this->xl->name, GF_LOG_TRACE,
1063                                "connect() -- already connected");
1064                        goto unlock;
1065                }
1066
1067                memcpy (&this->peerinfo.sockaddr, &sockaddr, sockaddr_len);
1068                this->peerinfo.sockaddr_len = sockaddr_len;
1069
1070                priv->sock = socket (sa_family, SOCK_STREAM, 0);
1071                if (priv->sock == -1) {
1072                        gf_log (this->xl->name, GF_LOG_ERROR,
1073                                "socket creation failed (%s)",
1074				strerror (errno));
1075                        goto unlock;
1076                }
1077
1078                /* Cant help if setting socket options fails. We can continue
1079                 * working nonetheless.
1080                 */
1081                if (setsockopt (priv->sock, SOL_SOCKET, SO_RCVBUF,
1082                                &priv->windowsize,
1083                                sizeof (priv->windowsize)) < 0) {
1084                        gf_log (this->xl->name, GF_LOG_ERROR,
1085                                "setting receive window size failed: %d: %d: "
1086                                "%s", priv->sock, priv->windowsize,
1087                                strerror (errno));
1088                }
1089
1090                if (setsockopt (priv->sock, SOL_SOCKET, SO_SNDBUF,
1091                                &priv->windowsize,
1092                                sizeof (priv->windowsize)) < 0) {
1093                        gf_log (this->xl->name, GF_LOG_ERROR,
1094                                "setting send window size failed: %d: %d: "
1095                                "%s", priv->sock, priv->windowsize,
1096                                strerror (errno));
1097                }
1098
1099
1100                if (priv->nodelay && priv->lowlat) {
1101                        ret = __socket_nodelay (priv->sock);
1102                        if (ret == -1) {
1103                                gf_log (this->xl->name, GF_LOG_ERROR,
1104                                        "setsockopt() failed for NODELAY (%s)",
1105                                        strerror (errno));
1106                        }
1107                }
1108
1109                if (!priv->bio) {
1110                        ret = __socket_nonblock (priv->sock);
1111
1112                        if (ret == -1) {
1113                                gf_log (this->xl->name, GF_LOG_ERROR,
1114                                        "NBIO on %d failed (%s)",
1115                                        priv->sock, strerror (errno));
1116                                close (priv->sock);
1117                                priv->sock = -1;
1118                                goto unlock;
1119                        }
1120                }
1121
1122                if (priv->keepalive) {
1123                        ret = __socket_keepalive (priv->sock,
1124                                                  priv->keepaliveintvl);
1125                        if (ret == -1)
1126                                gf_log (this->xl->name, GF_LOG_ERROR,
1127                                        "Failed to set keep-alive: %s",
1128                                        strerror (errno));
1129                }
1130
1131                SA (&this->myinfo.sockaddr)->sa_family =
1132			SA (&this->peerinfo.sockaddr)->sa_family;
1133
1134                ret = gf_client_bind (this, SA (&this->myinfo.sockaddr),
1135				   &this->myinfo.sockaddr_len, priv->sock);
1136                if (ret == -1) {
1137                        gf_log (this->xl->name, GF_LOG_WARNING,
1138                                "client bind failed: %s", strerror (errno));
1139                        close (priv->sock);
1140                        priv->sock = -1;
1141                        goto unlock;
1142                }
1143
1144                ret = connect (priv->sock, SA (&this->peerinfo.sockaddr),
1145			       this->peerinfo.sockaddr_len);
1146
1147                if (ret == -1 && errno != EINPROGRESS) {
1148                        gf_log (this->xl->name, GF_LOG_ERROR,
1149                                "connection attempt failed (%s)",
1150				strerror (errno));
1151                        close (priv->sock);
1152                        priv->sock = -1;
1153                        goto unlock;
1154                }
1155
1156                priv->connected = 0;
1157
1158                transport_ref (this);
1159
1160                priv->idx = event_register (ctx->event_pool, priv->sock,
1161                                            socket_event_handler, this, 1, 1);
1162                if (priv->idx == -1)
1163                        ret = -1;
1164        }
1165unlock:
1166        pthread_mutex_unlock (&priv->lock);
1167
1168err:
1169        return ret;
1170}
1171
1172
1173static int
1174socket_listen (transport_t *this)
1175{
1176        socket_private_t *       priv = NULL;
1177        int                      ret = -1;
1178	int                      sock = -1;
1179        struct sockaddr_storage  sockaddr;
1180        socklen_t                sockaddr_len;
1181        peer_info_t             *myinfo = NULL;
1182	glusterfs_ctx_t         *ctx = NULL;
1183        sa_family_t              sa_family = {0, };
1184
1185	priv   = this->private;
1186	myinfo = &this->myinfo;
1187	ctx    = this->xl->ctx;
1188
1189        pthread_mutex_lock (&priv->lock);
1190        {
1191                sock = priv->sock;
1192        }
1193        pthread_mutex_unlock (&priv->lock);
1194
1195        if (sock != -1)  {
1196                gf_log (this->xl->name, GF_LOG_DEBUG,
1197                        "already listening");
1198                return ret;
1199        }
1200
1201        ret = gf_socket_server_get_local_sockaddr (this, SA (&sockaddr),
1202                                                &sockaddr_len, &sa_family);
1203        if (ret == -1) {
1204                return ret;
1205        }
1206
1207        pthread_mutex_lock (&priv->lock);
1208        {
1209                if (priv->sock != -1) {
1210                        gf_log (this->xl->name, GF_LOG_DEBUG,
1211                                "already listening");
1212                        goto unlock;
1213                }
1214
1215                memcpy (&myinfo->sockaddr, &sockaddr, sockaddr_len);
1216                myinfo->sockaddr_len = sockaddr_len;
1217
1218                priv->sock = socket (sa_family, SOCK_STREAM, 0);
1219
1220                if (priv->sock == -1) {
1221                        gf_log (this->xl->name, GF_LOG_ERROR,
1222                                "socket creation failed (%s)",
1223				strerror (errno));
1224                        goto unlock;
1225                }
1226
1227                /* Cant help if setting socket options fails. We can continue
1228                 * working nonetheless.
1229                 */
1230                if (setsockopt (priv->sock, SOL_SOCKET, SO_RCVBUF,
1231                                &priv->windowsize,
1232                                sizeof (priv->windowsize)) < 0) {
1233                        gf_log (this->xl->name, GF_LOG_ERROR,
1234                                "setting receive window size failed: %d: %d: "
1235                                "%s", priv->sock, priv->windowsize,
1236                                strerror (errno));
1237                }
1238
1239                if (setsockopt (priv->sock, SOL_SOCKET, SO_SNDBUF,
1240                                &priv->windowsize,
1241                                sizeof (priv->windowsize)) < 0) {
1242                        gf_log (this->xl->name, GF_LOG_ERROR,
1243                               "setting send window size failed: %d: %d: "
1244                                "%s", priv->sock, priv->windowsize,
1245                                strerror (errno));
1246                }
1247
1248                if (priv->nodelay) {
1249                        ret = __socket_nodelay (priv->sock);
1250                        if (ret == -1) {
1251                                gf_log (this->xl->name, GF_LOG_ERROR,
1252                                        "setsockopt() failed for NODELAY (%s)",
1253                                        strerror (errno));
1254                        }
1255                }
1256
1257                if (!priv->bio) {
1258                        ret = __socket_nonblock (priv->sock);
1259
1260                        if (ret == -1) {
1261                                gf_log (this->xl->name, GF_LOG_ERROR,
1262                                        "NBIO on %d failed (%s)",
1263                                        priv->sock, strerror (errno));
1264                                close (priv->sock);
1265                                priv->sock = -1;
1266                                goto unlock;
1267                        }
1268                }
1269
1270                ret = __socket_server_bind (this);
1271
1272                if (ret == -1) {
1273                        /* logged inside __socket_server_bind() */
1274                        close (priv->sock);
1275                        priv->sock = -1;
1276                        goto unlock;
1277                }
1278
1279                ret = listen (priv->sock, 10);
1280
1281                if (ret == -1) {
1282                        gf_log (this->xl->name, GF_LOG_ERROR,
1283                                "could not set socket %d to listen mode (%s)",
1284				priv->sock, strerror (errno));
1285                        close (priv->sock);
1286                        priv->sock = -1;
1287                        goto unlock;
1288                }
1289
1290                transport_ref (this);
1291
1292                priv->idx = event_register (ctx->event_pool, priv->sock,
1293                                            socket_server_event_handler,
1294					    this, 1, 0);
1295
1296                if (priv->idx == -1) {
1297                        gf_log (this->xl->name, GF_LOG_DEBUG,
1298                                "could not register socket %d with events",
1299				priv->sock);
1300                        ret = -1;
1301                        close (priv->sock);
1302                        priv->sock = -1;
1303                        goto unlock;
1304                }
1305        }
1306unlock:
1307        pthread_mutex_unlock (&priv->lock);
1308
1309        return ret;
1310}
1311
1312
1313static int
1314socket_receive (transport_t *this, char **hdr_p, size_t *hdrlen_p,
1315                struct iobuf **iobuf_p)
1316{
1317        socket_private_t *priv = NULL;
1318        int               ret = -1;
1319
1320        priv = this->private;
1321
1322        pthread_mutex_lock (&priv->lock);
1323        {
1324                if (priv->connected != 1) {
1325                        gf_log (this->xl->name, GF_LOG_DEBUG,
1326                                "socket not connected to receive");
1327                        goto unlock;
1328                }
1329
1330                if (!hdr_p || !hdrlen_p || !iobuf_p) {
1331                        gf_log (this->xl->name, GF_LOG_DEBUG,
1332                                "bad parameters %p %p %p",
1333                                hdr_p, hdrlen_p, iobuf_p);
1334                        goto unlock;
1335                }
1336
1337                if (priv->incoming.state == SOCKET_PROTO_STATE_COMPLETE) {
1338                        *hdr_p    = priv->incoming.hdr_p;
1339                        *hdrlen_p = priv->incoming.hdrlen;
1340                        *iobuf_p  = priv->incoming.iobuf;
1341
1342                        memset (&priv->incoming, 0, sizeof (priv->incoming));
1343                        priv->incoming.state = SOCKET_PROTO_STATE_NADA;
1344
1345                        ret = 0;
1346                }
1347        }
1348unlock:
1349        pthread_mutex_unlock (&priv->lock);
1350
1351        return ret;
1352}
1353
1354
1355/* TODO: implement per transfer limit */
1356static int
1357socket_submit (transport_t *this, char *buf, int len,
1358               struct iovec *vector, int count,
1359               struct iobref *iobref)
1360{
1361        socket_private_t *priv = NULL;
1362        int               ret = -1;
1363        char              need_poll_out = 0;
1364        char              need_append = 1;
1365        struct ioq       *entry = NULL;
1366	glusterfs_ctx_t  *ctx = NULL;
1367
1368        priv = this->private;
1369	ctx  = this->xl->ctx;
1370
1371        pthread_mutex_lock (&priv->lock);
1372        {
1373                if (priv->connected != 1) {
1374                        if (!priv->submit_log && !priv->connect_finish_log) {
1375                                gf_log (this->xl->name, GF_LOG_DEBUG,
1376                                        "not connected (priv->connected = %d)",
1377                                        priv->connected);
1378                                priv->submit_log = 1;
1379                        }
1380                        goto unlock;
1381                }
1382
1383                priv->submit_log = 0;
1384                entry = __socket_ioq_new (this, buf, len, vector, count, iobref);
1385                if (!entry)
1386                        goto unlock;
1387
1388                if (list_empty (&priv->ioq)) {
1389                        ret = __socket_ioq_churn_entry (this, entry);
1390
1391                        if (ret == 0)
1392                                need_append = 0;
1393
1394                        if (ret > 0)
1395                                need_poll_out = 1;
1396                }
1397
1398                if (need_append) {
1399                        list_add_tail (&entry->list, &priv->ioq);
1400                        ret = 0;
1401                }
1402
1403                if (need_poll_out) {
1404                        /* first entry to wait. continue writing on POLLOUT */
1405                        priv->idx = event_select_on (ctx->event_pool,
1406						     priv->sock,
1407                                                     priv->idx, -1, 1);
1408                }
1409        }
1410unlock:
1411        pthread_mutex_unlock (&priv->lock);
1412
1413        return ret;
1414}
1415
1416
1417struct transport_ops tops = {
1418        .listen     = socket_listen,
1419        .connect    = socket_connect,
1420        .disconnect = socket_disconnect,
1421        .submit     = socket_submit,
1422        .receive    = socket_receive
1423};
1424
1425
1426static int
1427socket_init (transport_t *this)
1428{
1429        socket_private_t *priv = NULL;
1430        gf_boolean_t      tmp_bool = 0;
1431        uint64_t          windowsize = GF_DEFAULT_SOCKET_WINDOW_SIZE;
1432        char             *optstr = NULL;
1433        uint32_t          keepalive = 0;
1434
1435        if (this->private) {
1436                gf_log (this->xl->name, GF_LOG_DEBUG,
1437                        "double init attempted");
1438                return -1;
1439        }
1440
1441        priv = GF_CALLOC (1, sizeof (*priv), 
1442                         gf_common_mt_socket_private_t);
1443        if (!priv) {
1444                gf_log (this->xl->name, GF_LOG_ERROR,
1445                        "calloc (1, %"GF_PRI_SIZET") returned NULL",
1446			sizeof (*priv));
1447                return -1;
1448        }
1449
1450        pthread_mutex_init (&priv->lock, NULL);
1451
1452        priv->sock = -1;
1453        priv->idx = -1;
1454        priv->connected = -1;
1455
1456        INIT_LIST_HEAD (&priv->ioq);
1457
1458        if (dict_get (this->xl->options, "non-blocking-io")) {
1459                optstr = data_to_str (dict_get (this->xl->options,
1460                                                          "non-blocking-io"));
1461      
1462                if (gf_string2boolean (optstr, &tmp_bool) == -1) {
1463                        gf_log (this->xl->name, GF_LOG_ERROR,
1464                                "'non-blocking-io' takes only boolean options,"
1465				" not taking any action");
1466                        tmp_bool = 1;
1467                }
1468                priv->bio = 0;
1469                if (!tmp_bool) {
1470                        priv->bio = 1;
1471                        gf_log (this->xl->name, GF_LOG_WARNING,
1472                                "disabling non-blocking IO");
1473                }
1474        }
1475
1476        optstr = NULL;
1477        
1478        // By default, we enable NODELAY
1479        priv->nodelay = 1;
1480        if (dict_get (this->xl->options, "transport.socket.nodelay")) {
1481                optstr = data_to_str (dict_get (this->xl->options,
1482                                                "transport.socket.nodelay"));
1483
1484                if (gf_string2boolean (optstr, &tmp_bool) == -1) {
1485                        gf_log (this->xl->name, GF_LOG_ERROR,
1486                                "'transport.socket.nodelay' takes only "
1487                                 "boolean options, not taking any action");
1488                        tmp_bool = 1;
1489                }
1490                if (!tmp_bool) {
1491                        priv->nodelay = 0;
1492                        gf_log (this->xl->name, GF_LOG_DEBUG,
1493                                "disabling nodelay");
1494                }
1495        }
1496
1497
1498        optstr = NULL;
1499        if (dict_get_str (this->xl->options, "transport.window-size",
1500                          &optstr) == 0) {
1501                if (gf_string2bytesize (optstr, &windowsize) != 0) {
1502                        gf_log (this->xl->name, GF_LOG_ERROR,
1503                                "invalid number format: %s", optstr);
1504                        return -1;
1505                }
1506        }
1507
1508        optstr = NULL;
1509
1510        if (dict_get_str (this->xl->options, "transport.socket.lowlat",
1511                          &optstr) == 0) {
1512                priv->lowlat = 1;
1513        }
1514
1515        /* Enable Keep-alive by default. */
1516        priv->keepalive = 1;
1517        priv->keepaliveintvl = GF_USE_DEFAULT_KEEPALIVE;
1518        if (dict_get_str (this->xl->options, "transport.socket.keepalive",
1519                          &optstr) == 0) {
1520                if (gf_string2boolean (optstr, &tmp_bool) == -1) {
1521                        gf_log (this->xl->name, GF_LOG_ERROR,
1522                                "'transport.socket.keepalive' takes only "
1523                                 "boolean options, not taking any action");
1524                        tmp_bool = 1;
1525                }
1526
1527                if (!tmp_bool)
1528                        priv->keepalive = 0;
1529
1530        }
1531
1532        if (dict_get_uint32 (this->xl->options,
1533                             "transport.socket.keepalive-interval",
1534                             &keepalive) == 0) {
1535                priv->keepaliveintvl = keepalive;
1536        }
1537
1538        priv->windowsize = (int)windowsize;
1539        this->private = priv;
1540
1541        return 0;
1542}
1543
1544
1545void
1546fini (transport_t *this)
1547{
1548        socket_private_t *priv = this->private;
1549
1550        if (!priv)
1551                return;
1552        this->private = NULL;
1553        gf_log (this->xl->name, GF_LOG_TRACE,
1554                "transport %p destroyed", this);
1555
1556        pthread_mutex_destroy (&priv->lock);
1557        GF_FREE (priv);
1558}
1559
1560
1561int32_t
1562init (transport_t *this)
1563{
1564        int ret = -1;
1565
1566        ret = socket_init (this);
1567
1568        if (ret == -1) {
1569                gf_log (this->xl->name, GF_LOG_DEBUG, "socket_init() failed");
1570        }
1571  
1572        return ret;
1573}
1574
1575struct volume_options options[] = {
1576        { .key   = {"remote-port", 
1577                    "transport.remote-port",
1578                    "transport.socket.remote-port"}, 
1579          .type  = GF_OPTION_TYPE_INT 
1580        },
1581        { .key   = {"transport.socket.listen-port", "listen-port"}, 
1582          .type  = GF_OPTION_TYPE_INT 
1583        },
1584        { .key   = {"transport.socket.bind-address", "bind-address" }, 
1585          .type  = GF_OPTION_TYPE_INTERNET_ADDRESS 
1586        },
1587        { .key   = {"transport.socket.connect-path", "connect-path"}, 
1588          .type  = GF_OPTION_TYPE_ANY 
1589        },
1590        { .key   = {"transport.socket.bind-path", "bind-path"}, 
1591          .type  = GF_OPTION_TYPE_ANY 
1592        },
1593        { .key   = {"transport.socket.listen-path", "listen-path"}, 
1594          .type  = GF_OPTION_TYPE_ANY 
1595        },
1596        { .key   = { "transport.address-family",
1597                     "address-family" }, 
1598          .value = {"inet", "inet6", "inet/inet6", "inet6/inet",
1599                    "unix", "inet-sdp" },
1600          .type  = GF_OPTION_TYPE_STR 
1601        },
1602
1603        { .key   = {"non-blocking-io"}, 
1604          .type  = GF_OPTION_TYPE_BOOL
1605        },
1606        { .key   = {"transport.window-size"},
1607          .type  = GF_OPTION_TYPE_SIZET,
1608          .min   = GF_MIN_SOCKET_WINDOW_SIZE,
1609          .max   = GF_MAX_SOCKET_WINDOW_SIZE,
1610        },
1611        { .key   = {"transport.socket.nodelay"},
1612          .type  = GF_OPTION_TYPE_BOOL
1613        },
1614        { .key   = {"transport.socket.lowlat"},
1615          .type  = GF_OPTION_TYPE_BOOL
1616        },
1617        { .key   = {"transport.socket.keepalive"},
1618          .type  = GF_OPTION_TYPE_BOOL
1619        },
1620        { .key   = {"transport.socket.keepalive-interval"},
1621          .type  = GF_OPTION_TYPE_INT
1622        },
1623        { .key = {NULL} }
1624};
1625