Esempio n. 1
0
errno_t xi_sock_receivefrom(xi_socket_t so, void *buf, size_t *len, int flags, struct sockaddr *from, int *fromlen) {

	struct iovec aio;
	errno_t			error;
	
#ifdef __KPI_SOCKET__
	
	struct msghdr msg;
	size_t			recvLen;
	
	aio.iov_base = buf;
	aio.iov_len = *len;
	bzero(&msg, sizeof(msg));
	msg.msg_iov = (struct iovec *) &aio;
	msg.msg_iovlen = 1;
	
	if(from != NULL && fromlen != NULL && *fromlen > 0) {
		msg.msg_name = from;
		msg.msg_namelen = *fromlen;
	}
	
	error = sock_receive(so, &msg, flags, &recvLen);
	
	*len = recvLen;
	
	return error;

#else
		
    struct uio auio;
	struct sockaddr *fromsa = 0;
	
	aio.iov_base = (char *)buf;
	aio.iov_len = *len;
	
	auio.uio_iov = &aio;
	auio.uio_iovcnt = 1;
	auio.uio_segflg = UIO_SYSSPACE;
	auio.uio_rw = UIO_READ;
	auio.uio_offset = 0;                    /* XXX */
	auio.uio_resid = *len;
	
	thread_funnel_set(network_flock, TRUE);
				
	error = soreceive(so, &fromsa, &auio, NULL, 0, &flags);
	
	(void)thread_funnel_set(network_flock, FALSE);

	if (from != NULL && fromsa) {
		bcopy(fromsa, from, sizeof(struct sockaddr_lpx));
		
		FREE(fromsa, M_SONAME);
	}

	*len =  *len - auio.uio_resid;

	return error;
#endif
	
}
Esempio n. 2
0
int
libcfs_sock_read (cfs_socket_t *sock, void *buffer, int nob, int timeout)
{
        size_t          rcvlen;
        int             rc;
        cfs_duration_t  to = cfs_time_seconds(timeout);
        cfs_time_t      then;
        struct timeval  tv;

        LASSERT(nob > 0);

        for (;;) {
                struct iovec  iov = {
                        .iov_base = buffer,
                        .iov_len  = nob
                };
                struct  msghdr  msg = {
                        .msg_name       = NULL,
                        .msg_namelen    = 0,
                        .msg_iov        = &iov,
                        .msg_iovlen     = 1,
                        .msg_control    = NULL,
                        .msg_controllen = 0,
                        .msg_flags      = 0,
                };
                cfs_duration_usec(to, &tv);
                rc = -sock_setsockopt(C2B_SOCK(sock), SOL_SOCKET, SO_RCVTIMEO,
                                      &tv, sizeof(tv));
                if (rc != 0) {
                        CERROR("Can't set socket recv timeout "
                                        "%ld.%06d: %d\n",
                                        (long)tv.tv_sec, (int)tv.tv_usec, rc);
                        return rc;
                }

                then = cfs_time_current();
                rc = -sock_receive(C2B_SOCK(sock), &msg, 0, &rcvlen);
                to -= cfs_time_current() - then;

                if (rc != 0 && rc != -EWOULDBLOCK)
                        return rc;
                if (rcvlen == nob)
                        return 0;

                if (to <= 0)
                        return -EAGAIN;

                buffer = ((char *)buffer) + rcvlen;
                nob -= rcvlen;
        }
        return 0;
}

int
libcfs_sock_write (cfs_socket_t *sock, void *buffer, int nob, int timeout)
{
        size_t          sndlen;
        int             rc;
        cfs_duration_t  to = cfs_time_seconds(timeout);
        cfs_time_t      then;
        struct timeval  tv;

        LASSERT(nob > 0);

        for (;;) {
                struct iovec  iov = {
                        .iov_base = buffer,
                        .iov_len  = nob
                };
                struct  msghdr  msg = {
                        .msg_name       = NULL,
                        .msg_namelen    = 0,
                        .msg_iov        = &iov,
                        .msg_iovlen     = 1,
                        .msg_control    = NULL,
                        .msg_controllen = 0,
                        .msg_flags      = (timeout == 0) ? MSG_DONTWAIT : 0,
                };

                if (timeout != 0) {
                        cfs_duration_usec(to, &tv);
                        rc = -sock_setsockopt(C2B_SOCK(sock), SOL_SOCKET, SO_SNDTIMEO,
                                              &tv, sizeof(tv));
                        if (rc != 0) {
                                CERROR("Can't set socket send timeout "
                                       "%ld.%06d: %d\n",
                                       (long)tv.tv_sec, (int)tv.tv_usec, rc);
                                return rc;
                        }
                }

                then = cfs_time_current();
                rc = -sock_send(C2B_SOCK(sock), &msg, 
                                ((timeout == 0) ? MSG_DONTWAIT : 0), &sndlen);
                to -= cfs_time_current() - then;

                if (rc != 0 && rc != -EWOULDBLOCK)
                        return rc;
                if (sndlen == nob)
                        return 0;

                if (to <= 0)
                        return -EAGAIN;
                buffer = ((char *)buffer) + sndlen;
                nob -= sndlen;
        }
        return 0;

}

int
libcfs_sock_getaddr (cfs_socket_t *sock, int remote, __u32 *ip, int *port)
{
        struct sockaddr_in sin;
        int                rc;

        if (remote != 0) 
                /* Get remote address */
                rc = -sock_getpeername(C2B_SOCK(sock), (struct sockaddr *)&sin, sizeof(sin));
        else 
                /* Get local address */
                rc = -sock_getsockname(C2B_SOCK(sock), (struct sockaddr *)&sin, sizeof(sin));
        if (rc != 0) {
                CERROR ("Error %d getting sock %s IP/port\n",
                         rc, remote ? "peer" : "local");
                return rc;
        }

        if (ip != NULL)
                *ip = ntohl (sin.sin_addr.s_addr);

        if (port != NULL)
                *port = ntohs (sin.sin_port);
        return 0;
}

int
libcfs_sock_setbuf (cfs_socket_t *sock, int txbufsize, int rxbufsize)
{
        int                 option;
        int                 rc;
        
        if (txbufsize != 0) {
                option = txbufsize;
                rc = -sock_setsockopt(C2B_SOCK(sock), SOL_SOCKET, SO_SNDBUF,
                                     (char *)&option, sizeof (option));
                if (rc != 0) {
                        CERROR ("Can't set send buffer %d: %d\n",
                                option, rc);
                        return (rc);
                } 
        } 
        
        if (rxbufsize != 0) {
                option = rxbufsize;
                rc = -sock_setsockopt (C2B_SOCK(sock), SOL_SOCKET, SO_RCVBUF,
                                      (char *)&option, sizeof (option));
                if (rc != 0) {
                        CERROR ("Can't set receive buffer %d: %d\n",
                                option, rc);
                        return (rc);
                }
        }
        return 0;
}
Esempio n. 3
0
File: krpc_subr.c Progetto: argp/xnu
/*
 * Do a remote procedure call (RPC) and wait for its reply.
 * If from_p is non-null, then we are doing broadcast, and
 * the address from whence the response came is saved there.
 */
int
krpc_call(
	struct sockaddr_in *sa,
	u_int sotype, u_int prog, u_int vers, u_int func,
	mbuf_t *data,			/* input/output */
	struct sockaddr_in *from_p)	/* output */
{
	socket_t so;
	struct sockaddr_in *sin;
	mbuf_t m, nam, mhead;
	struct rpc_call *call;
	struct rpc_reply *reply;
	int error, timo, secs;
	size_t len;
	static u_int32_t xid = ~0xFF;
	u_int16_t tport;
	size_t maxpacket = 1<<16;

	/*
	 * Validate address family.
	 * Sorry, this is INET specific...
	 */
	if (sa->sin_family != AF_INET)
		return (EAFNOSUPPORT);

	/* Free at end if not null. */
	nam = mhead = NULL;

	/*
	 * Create socket and set its recieve timeout.
	 */
	if ((error = sock_socket(AF_INET, sotype, 0, 0, 0, &so)))
		goto out1;

	{
		struct timeval tv;

		tv.tv_sec = 1;
		tv.tv_usec = 0;

		if ((error = sock_setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))))
		    goto out;

	}

	/*
	 * Enable broadcast if necessary.
	 */

	if (from_p && (sotype == SOCK_DGRAM)) {
		int on = 1;
		if ((error = sock_setsockopt(so, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on))))
			goto out;
	}

	/*
	 * Bind the local endpoint to a reserved port,
	 * because some NFS servers refuse requests from
	 * non-reserved (non-privileged) ports.
	 */
	if ((error = mbuf_get(MBUF_WAITOK, MBUF_TYPE_SONAME, &m)))
		goto out;
	sin = mbuf_data(m);
	bzero(sin, sizeof(*sin));
	mbuf_setlen(m, sizeof(*sin));
	sin->sin_len = sizeof(*sin);
	sin->sin_family = AF_INET;
	sin->sin_addr.s_addr = INADDR_ANY;
	tport = IPPORT_RESERVED;
	do {
		tport--;
		sin->sin_port = htons(tport);
		error = sock_bind(so, (struct sockaddr*)sin);
	} while (error == EADDRINUSE &&
			 tport > IPPORT_RESERVED / 2);
	mbuf_freem(m);
	m = NULL;
	if (error) {
		printf("bind failed\n");
		goto out;
	}

	/*
	 * Setup socket address for the server.
	 */
	if ((error = mbuf_get(MBUF_WAITOK, MBUF_TYPE_SONAME, &nam)))
		goto out;
	sin = mbuf_data(nam);
	mbuf_setlen(nam, sa->sin_len);
	bcopy((caddr_t)sa, (caddr_t)sin, sa->sin_len);

	if (sotype == SOCK_STREAM) {
		struct timeval tv;
		tv.tv_sec = 60;
		tv.tv_usec = 0;
		error = sock_connect(so, mbuf_data(nam), MSG_DONTWAIT);
		if (error && (error != EINPROGRESS))
			goto out;
		error = sock_connectwait(so, &tv);
		if (error) {
			if (error == EINPROGRESS)
				error = ETIMEDOUT;
			printf("krpc_call: error waiting for TCP socket connect: %d\n", error);
			goto out;
		}
	}

	/*
	 * Prepend RPC message header.
	 */
	m = *data;
	*data = NULL;
#if	DIAGNOSTIC
	if ((mbuf_flags(m) & MBUF_PKTHDR) == 0)
		panic("krpc_call: send data w/o pkthdr");
	if (mbuf_pkthdr_len(m) < mbuf_len(m))
		panic("krpc_call: pkthdr.len not set");
#endif
	len = sizeof(*call);
	if (sotype == SOCK_STREAM)
		len += 4;  /* account for RPC record marker */
	mhead = m;
	if ((error = mbuf_prepend(&mhead, len, MBUF_WAITOK)))
		goto out;
	if ((error = mbuf_pkthdr_setrcvif(mhead, NULL)))
		goto out;

	/*
	 * Fill in the RPC header
	 */
	if (sotype == SOCK_STREAM) {
		/* first, fill in RPC record marker */
		u_int32_t *recmark = mbuf_data(mhead);
		*recmark = htonl(0x80000000 | (mbuf_pkthdr_len(mhead) - 4));
		call = (struct rpc_call *)(recmark + 1);
	} else {
		call = mbuf_data(mhead);
	}
	bzero((caddr_t)call, sizeof(*call));
	xid++;
	call->rp_xid = htonl(xid);
	/* call->rp_direction = 0; */
	call->rp_rpcvers = htonl(2);
	call->rp_prog = htonl(prog);
	call->rp_vers = htonl(vers);
	call->rp_proc = htonl(func);
	/* call->rp_auth = 0; */
	/* call->rp_verf = 0; */

	/*
	 * Send it, repeatedly, until a reply is received,
	 * but delay each re-send by an increasing amount.
	 * If the delay hits the maximum, start complaining.
	 */
	timo = 0;
	for (;;) {
		struct msghdr msg;
		
		/* Send RPC request (or re-send). */
		if ((error = mbuf_copym(mhead, 0, MBUF_COPYALL, MBUF_WAITOK, &m)))
			goto out;
		bzero(&msg, sizeof(msg));
		if (sotype == SOCK_STREAM) {
			msg.msg_name = NULL;
			msg.msg_namelen = 0;
		} else {
			msg.msg_name = mbuf_data(nam);
			msg.msg_namelen = mbuf_len(nam);
		}
		error = sock_sendmbuf(so, &msg, m, 0, 0);
		if (error) {
			printf("krpc_call: sosend: %d\n", error);
			goto out;
		}
		m = NULL;

		/* Determine new timeout. */
		if (timo < MAX_RESEND_DELAY)
			timo++;
            	else
           		printf("RPC timeout for server " IP_FORMAT "\n",
				IP_LIST(&(sin->sin_addr.s_addr)));

		/*
		 * Wait for up to timo seconds for a reply.
		 * The socket receive timeout was set to 1 second.
		 */
		secs = timo;
		while (secs > 0) {
			size_t readlen;
			
			if (m) {
				mbuf_freem(m);
				m = NULL;
			}
			if (sotype == SOCK_STREAM) {
				int maxretries = 60;
				struct iovec aio;
				aio.iov_base = &len;
				aio.iov_len = sizeof(u_int32_t);
				bzero(&msg, sizeof(msg));
				msg.msg_iov = &aio;
				msg.msg_iovlen = 1;
				do {
				   error = sock_receive(so, &msg, MSG_WAITALL, &readlen);
				   if ((error == EWOULDBLOCK) && (--maxretries <= 0))
					error = ETIMEDOUT;
				} while (error == EWOULDBLOCK);
				if (!error && readlen < aio.iov_len) {
				    /* only log a message if we got a partial word */
				    if (readlen != 0)
					    printf("short receive (%ld/%ld) from server " IP_FORMAT "\n",
						 readlen, sizeof(u_int32_t), IP_LIST(&(sin->sin_addr.s_addr)));
				    error = EPIPE;
				}
				if (error)
					goto out;
				len = ntohl(len) & ~0x80000000;
				/*
				 * This is SERIOUS! We are out of sync with the sender
				 * and forcing a disconnect/reconnect is all I can do.
				 */
				if (len > maxpacket) {
				    printf("impossible packet length (%ld) from server " IP_FORMAT "\n",
					len, IP_LIST(&(sin->sin_addr.s_addr)));
				    error = EFBIG;
				    goto out;
				}
				
				do {
				    readlen = len;
				    error = sock_receivembuf(so, NULL, &m, MSG_WAITALL, &readlen);
				} while (error == EWOULDBLOCK);

				if (!error && (len > readlen)) {
				    printf("short receive (%ld/%ld) from server " IP_FORMAT "\n",
					readlen, len, IP_LIST(&(sin->sin_addr.s_addr)));
				    error = EPIPE;
				}
			} else {
				len = maxpacket;
				readlen = len;
				bzero(&msg, sizeof(msg));
				msg.msg_name = from_p;
				msg.msg_namelen = (from_p == NULL) ? 0 : sizeof(*from_p);
				error = sock_receivembuf(so, &msg, &m, 0, &readlen);
			}

			if (error == EWOULDBLOCK) {
				secs--;
				continue;
			}
			if (error)
				goto out;
			len = readlen;

			/* Does the reply contain at least a header? */
			if (len < MIN_REPLY_HDR)
				continue;
			if (mbuf_len(m) < MIN_REPLY_HDR)
				continue;
			reply = mbuf_data(m);

			/* Is it the right reply? */
			if (reply->rp_direction != htonl(RPC_REPLY))
				continue;

			if (reply->rp_xid != htonl(xid))
				continue;
			
			/* Was RPC accepted? (authorization OK) */
			if (reply->rp_astatus != 0) {
				error = ntohl(reply->rp_u.rpu_errno);
				printf("rpc denied, error=%d\n", error);
				/* convert rpc error to errno */
				switch (error) {
				case RPC_MISMATCH:
					error = ERPCMISMATCH;
					break;
				case RPC_AUTHERR:
					error = EAUTH;
					break;
				}
				goto out;
			}


			if (mbuf_len(m) < REPLY_SIZE) {
				error = RPC_SYSTEM_ERR;
			}
			else {
				error = ntohl(reply->rp_u.rpu_ok.rp_rstatus);
			}

			/* Did the call succeed? */
			if (error != 0) {
				printf("rpc status=%d\n", error);
				/* convert rpc error to errno */
				switch (error) {
				case RPC_PROGUNAVAIL:
					error = EPROGUNAVAIL;
					break;
				case RPC_PROGMISMATCH:
					error = EPROGMISMATCH;
					break;
				case RPC_PROCUNAVAIL:
					error = EPROCUNAVAIL;
					break;
				case RPC_GARBAGE:
					error = EINVAL;
					break;
				case RPC_SYSTEM_ERR:
					error = EIO;
					break;
				}
				goto out;
			}

			goto gotreply;	/* break two levels */

		} /* while secs */
	} /* forever send/receive */

	error = ETIMEDOUT;
	goto out;

 gotreply:

	/*
	 * Pull as much as we can into first mbuf, to make
	 * result buffer contiguous.  Note that if the entire
	 * result won't fit into one mbuf, you're out of luck.
	 * XXX - Should not rely on making the entire reply
	 * contiguous (fix callers instead). -gwr
	 */
#if	DIAGNOSTIC
	if ((mbuf_flags(m) & MBUF_PKTHDR) == 0)
		panic("krpc_call: received pkt w/o header?");
#endif
	len = mbuf_pkthdr_len(m);
	if (sotype == SOCK_STREAM)
		len -= 4;  /* the RPC record marker was read separately */
	if (mbuf_len(m) < len) {
		if ((error = mbuf_pullup(&m, len)))
			goto out;
		reply = mbuf_data(m);
	}

	/*
	 * Strip RPC header
	 */
	len = sizeof(*reply);
	if (reply->rp_u.rpu_ok.rp_auth.rp_atype != 0) {
		len += ntohl(reply->rp_u.rpu_ok.rp_auth.rp_alen);
		len = (len + 3) & ~3; /* XXX? */
	}
	mbuf_adj(m, len);

	/* result */
	*data = m;
 out:
	sock_close(so);
out1:
	if (nam) mbuf_freem(nam);
	if (mhead) mbuf_freem(mhead);
	return error;
}
Esempio n. 4
0
  int
  KeyRemap4MacBook_client::sendmsg(KeyRemap4MacBook_bridge::RequestType type, void* request, uint32_t requestsize, void* reply, uint32_t replysize)
  {
    if (! lock_) { return EIO; }

    IOLockWrapper::ScopedLock lk(lock_);

    if (type == KeyRemap4MacBook_bridge::REQUEST_STATUS_MESSAGE) {
      if (config.general_hide_statusmessage) {
        if (! request) return 0;
        char* p = reinterpret_cast<KeyRemap4MacBook_bridge::StatusMessage::Request*>(request)->message;
        if (p[0] != '\0') {
          return 0;
        }
      }
    }

    // ------------------------------------------------------------
    int result = 0;
    int error = 0;
    socket_t socket;
    bool isMakeSocket = false;

    if (! makeSocket(socket)) {
      result = EIO;
      goto finish;
    }
    isMakeSocket = true;

    if (! connectSocket(socket)) {
      result = EIO;
      goto finish;
    }

    // ----------------------------------------
    struct msghdr msg;
    memset(&msg, 0, sizeof(msg));

    struct iovec aiov[3];
    size_t iolen;
    aiov[0].iov_base = reinterpret_cast<caddr_t>(&type);
    aiov[0].iov_len = sizeof(type);
    if (requestsize <= 0) {
      msg.msg_iovlen = 1;
    } else {
      aiov[1].iov_base = reinterpret_cast<caddr_t>(&requestsize);
      aiov[1].iov_len = sizeof(requestsize);
      aiov[2].iov_base = reinterpret_cast<caddr_t>(request);
      aiov[2].iov_len = requestsize;
      msg.msg_iovlen = 3;
    }
    msg.msg_iov = aiov;

    error = sock_send(socket, &msg, 0, &iolen);
    if (error) {
      printf("KeyRemap4MacBook_client::sendmsg sock_send failed(%d)\n", error);
      result = error;
      goto finish;
    }

    // ----------------------------------------
    if (replysize > 0) {
      memset(&msg, 0, sizeof(msg));

      uint32_t status = -1;
      aiov[0].iov_base = reinterpret_cast<caddr_t>(&status);
      aiov[0].iov_len = sizeof(status);
      aiov[1].iov_base = reinterpret_cast<caddr_t>(reply);
      aiov[1].iov_len = replysize;
      msg.msg_iov = aiov;
      msg.msg_iovlen = 2;

      error = sock_receive(socket, &msg, MSG_WAITALL, &iolen);
      if (error) {
        printf("KeyRemap4MacBook_client::sendmsg sock_receive failed(%d)\n", error);
        result = error;
        goto finish;
      }
    }

  finish:
    if (isMakeSocket) {
      releaseSocket(socket);
    }
    if (result) {
      printf("KeyRemap4MacBook_client::sendmsg error result (%d)\n", result);
    }
    return result;
  }
Esempio n. 5
0
int
ksocknal_lib_send_iov (ksock_conn_t *conn, ksock_tx_t *tx)
{
        socket_t        sock = C2B_SOCK(conn->ksnc_sock);
        size_t          sndlen;
        int             nob;
        int             rc;

#if SOCKNAL_SINGLE_FRAG_TX
        struct iovec    scratch;
        struct iovec   *scratchiov = &scratch;
        unsigned int    niov = 1;
#else
        struct iovec   *scratchiov = conn->ksnc_scheduler->kss_scratch_iov;
        unsigned int    niov = tx->tx_niov;
#endif
        struct msghdr msg = {
                .msg_name       = NULL,
                .msg_namelen    = 0,
                .msg_iov        = scratchiov,
                .msg_iovlen     = niov,
                .msg_control    = NULL,
                .msg_controllen = 0,
                .msg_flags      = MSG_DONTWAIT
        };
        
        int  i;
        
        for (nob = i = 0; i < niov; i++) {
                scratchiov[i] = tx->tx_iov[i];
                nob += scratchiov[i].iov_len;
        } 
        
        /* 
         * XXX Liang:
         * Linux has MSG_MORE, do we have anything to
         * reduce number of partial TCP segments sent?
         */
        rc = -sock_send(sock, &msg, MSG_DONTWAIT, &sndlen);
        if (rc == 0)
                rc = sndlen;
        return rc;
}

int
ksocknal_lib_send_kiov (ksock_conn_t *conn, ksock_tx_t *tx)
{
        socket_t       sock = C2B_SOCK(conn->ksnc_sock);
        lnet_kiov_t   *kiov = tx->tx_kiov;
        int            rc;
        int            nob;
        size_t         sndlen;

#if SOCKNAL_SINGLE_FRAG_TX
        struct iovec  scratch;
        struct iovec *scratchiov = &scratch;
        unsigned int  niov = 1;
#else
        struct iovec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov;
        unsigned int  niov = tx->tx_nkiov;
#endif
        struct msghdr msg = {
                .msg_name       = NULL,
                .msg_namelen    = 0,
                .msg_iov        = scratchiov,
                .msg_iovlen     = niov,
                .msg_control    = NULL,
                .msg_controllen = 0,
                .msg_flags      = MSG_DONTWAIT
        };
        
        int           i;
        
        for (nob = i = 0; i < niov; i++) {
                scratchiov[i].iov_base = cfs_kmap(kiov[i].kiov_page) +
                                         kiov[i].kiov_offset;
                nob += scratchiov[i].iov_len = kiov[i].kiov_len;
        }

        /* 
         * XXX Liang:
         * Linux has MSG_MORE, do wen have anyting to
         * reduce number of partial TCP segments sent?
         */
        rc = -sock_send(sock, &msg, MSG_DONTWAIT, &sndlen);
        for (i = 0; i < niov; i++)
                cfs_kunmap(kiov[i].kiov_page);
        if (rc == 0)
                rc = sndlen;
        return rc;
}

int
ksocknal_lib_recv_iov (ksock_conn_t *conn)
{
#if SOCKNAL_SINGLE_FRAG_RX
        struct iovec  scratch;
        struct iovec *scratchiov = &scratch;
        unsigned int  niov = 1;
#else
        struct iovec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov;
        unsigned int  niov = conn->ksnc_rx_niov;
#endif
        struct iovec *iov = conn->ksnc_rx_iov;
        struct msghdr msg = {
                .msg_name       = NULL,
                .msg_namelen    = 0,
                .msg_iov        = scratchiov,
                .msg_iovlen     = niov,
                .msg_control    = NULL,
                .msg_controllen = 0,
                .msg_flags      = 0
        };
        size_t       rcvlen;
        int          nob;
        int          i;
        int          rc;

        LASSERT (niov > 0);

        for (nob = i = 0; i < niov; i++) {
                scratchiov[i] = iov[i];
                nob += scratchiov[i].iov_len;
        }
        LASSERT (nob <= conn->ksnc_rx_nob_wanted); 
        rc = -sock_receive (C2B_SOCK(conn->ksnc_sock), &msg, MSG_DONTWAIT, &rcvlen);
        if (rc == 0)
                rc = rcvlen;

        return rc;
}

int
ksocknal_lib_recv_kiov (ksock_conn_t *conn)
{
#if SOCKNAL_SINGLE_FRAG_RX
        struct iovec  scratch;
        struct iovec *scratchiov = &scratch;
        unsigned int  niov = 1;
#else
        struct iovec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov;
        unsigned int  niov = conn->ksnc_rx_nkiov;
#endif
        lnet_kiov_t   *kiov = conn->ksnc_rx_kiov;
        struct msghdr msg = {
                .msg_name       = NULL,
                .msg_namelen    = 0,
                .msg_iov        = scratchiov,
                .msg_iovlen     = niov,
                .msg_control    = NULL,
                .msg_controllen = 0,
                .msg_flags      = 0
        };
        int          nob;
        int          i;
        size_t       rcvlen;
        int          rc;

        /* NB we can't trust socket ops to either consume our iovs
         * or leave them alone. */
        for (nob = i = 0; i < niov; i++) {
                scratchiov[i].iov_base = cfs_kmap(kiov[i].kiov_page) + \
                                         kiov[i].kiov_offset;
                nob += scratchiov[i].iov_len = kiov[i].kiov_len;
        }
        LASSERT (nob <= conn->ksnc_rx_nob_wanted);
        rc = -sock_receive(C2B_SOCK(conn->ksnc_sock), &msg, MSG_DONTWAIT, &rcvlen); 
        for (i = 0; i < niov; i++)
                cfs_kunmap(kiov[i].kiov_page); 
        if (rc == 0)
                rc = rcvlen;
        return (rc);
}

void
ksocknal_lib_eager_ack (ksock_conn_t *conn)
{
        /* XXX Liang: */
}

int
ksocknal_lib_get_conn_tunables (ksock_conn_t *conn, int *txmem, int *rxmem, int *nagle)
{
        socket_t       sock = C2B_SOCK(conn->ksnc_sock);
        int            len;
        int            rc;

        rc = ksocknal_connsock_addref(conn);
        if (rc != 0) {
                LASSERT (conn->ksnc_closing);
                *txmem = *rxmem = *nagle = 0;
                return (-ESHUTDOWN);
        }
        rc = libcfs_sock_getbuf(conn->ksnc_sock, txmem, rxmem);
        if (rc == 0) {
                len = sizeof(*nagle);
                rc = -sock_getsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
                                      nagle, &len);
        }
        ksocknal_connsock_decref(conn);

        if (rc == 0)
                *nagle = !*nagle;
        else
                *txmem = *rxmem = *nagle = 0;

        return (rc);
}

int
ksocknal_lib_setup_sock (cfs_socket_t *sock)
{
        int             rc; 
        int             option; 
        int             keep_idle; 
        int             keep_intvl; 
        int             keep_count; 
        int             do_keepalive; 
        socket_t        so = C2B_SOCK(sock);
        struct linger   linger;

        /* Ensure this socket aborts active sends immediately when we close
         * it. */
        linger.l_onoff = 0;
        linger.l_linger = 0;
        rc = -sock_setsockopt(so, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger));
        if (rc != 0) {
                CERROR ("Can't set SO_LINGER: %d\n", rc);
                return (rc);
        }

        if (!*ksocknal_tunables.ksnd_nagle) { 
                option = 1; 
                rc = -sock_setsockopt(so, IPPROTO_TCP, TCP_NODELAY, &option, sizeof(option));
                if (rc != 0) { 
                        CERROR ("Can't disable nagle: %d\n", rc); 
                        return (rc);
                } 
        } 

        rc = libcfs_sock_setbuf(sock,
                                *ksocknal_tunables.ksnd_tx_buffer_size,
                                *ksocknal_tunables.ksnd_rx_buffer_size);
        if (rc != 0) {
                CERROR ("Can't set buffer tx %d, rx %d buffers: %d\n",
                        *ksocknal_tunables.ksnd_tx_buffer_size,
                        *ksocknal_tunables.ksnd_rx_buffer_size, rc);
                return (rc);
        }

        /* snapshot tunables */ 
        keep_idle  = *ksocknal_tunables.ksnd_keepalive_idle; 
        keep_count = *ksocknal_tunables.ksnd_keepalive_count; 
        keep_intvl = *ksocknal_tunables.ksnd_keepalive_intvl;

        do_keepalive = (keep_idle > 0 && keep_count > 0 && keep_intvl > 0); 
        option = (do_keepalive ? 1 : 0); 

        rc = -sock_setsockopt(so, SOL_SOCKET, SO_KEEPALIVE, &option, sizeof(option)); 
        if (rc != 0) { 
                CERROR ("Can't set SO_KEEPALIVE: %d\n", rc); 
                return (rc);
        }
        
        if (!do_keepalive)
                return (rc);
        rc = -sock_setsockopt(so, IPPROTO_TCP, TCP_KEEPALIVE, 
                              &keep_idle, sizeof(keep_idle));
        
        return (rc);
}

void
ksocknal_lib_push_conn(ksock_conn_t *conn)
{ 
        socket_t        sock; 
        int             val = 1; 
        int             rc; 
        
        rc = ksocknal_connsock_addref(conn); 
        if (rc != 0)            /* being shut down */ 
                return; 
        sock = C2B_SOCK(conn->ksnc_sock); 

        rc = -sock_setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); 
        LASSERT(rc == 0);

        ksocknal_connsock_decref(conn);
        return;
}
Esempio n. 6
0
int main(int argc, char **argv)
{
	int c;
	risp_t *risp;
	int sent;
	char *srv = "127.0.0.1";
	char *filename = NULL;
	int port = DEFAULT_PORT;
	int avail;
	int processed;
	int len;
	int done = 0, t;

	node_t node;

	// initialise the node data.
	node.handle = INVALID_HANDLE;
	node.verbose = 0;
	node.finished = 0;
	expbuf_init(&node.in, 1024);
	expbuf_init(&node.out, 1024);
	expbuf_init(&node.data.file, 0);
	expbuf_init(&node.data.data, 0);
	node.data.op = CMD_NOP;
	node.data.size = 0;
	node.data.offset = 0;

	node.filehandle = INVALID_HANDLE;
	node.size = 0;
	node.offset = 0;


	while ((c = getopt(argc, argv, "f:p:s:v")) != -1) {
		switch (c) {
			case 'f':
				filename = optarg;
				assert(filename != NULL);
				break;
			case 'p':
				port = atoi(optarg);
				assert(port > 0);
				break;
			case 's':
				srv = optarg;
				assert(srv != NULL);
				break;
			case 'v':
				node.verbose ++;
				break;
			default:
				fprintf(stderr, "Illegal argument \"%c\"\n", c);
				return 1;
		}
	}

	if (filename == NULL) {
		fprintf(stderr, "Need a filename.\n\n");
		exit(1);
	}

	// get an initialised risp structure.
	risp = risp_init();
	if (risp == NULL) {
		printf("Unable to initialise RISP library.\n");
	}
	else {
		risp_add_command(risp, CMD_CLEAR, 	&cmdClear);
		risp_add_command(risp, CMD_EXECUTE, &cmdExecute);
		risp_add_command(risp, CMD_OFFSET,  &cmdOffset);
		risp_add_command(risp, CMD_SIZE,    &cmdSize);
		risp_add_command(risp, CMD_FILE,    &cmdFile);
		risp_add_command(risp, CMD_DATA,    &cmdData);
		risp_add_command(risp, CMD_PUT,     &cmdPut);
		risp_add_command(risp, CMD_GET,     &cmdGet);
		
		len = strlen(filename);
		assert(len < 256);

		assert(node.out.length == 0);
		
		addCmd(&node.out, CMD_CLEAR);
		addCmd(&node.out, CMD_GET);
		addCmdShortStr(&node.out, CMD_FILE, len, filename);
		addCmd(&node.out, CMD_EXECUTE);
		
		// and process it a lot of time.
		printf("Sending request for: %s\n", filename);
		
		// connect to the remote socket.
		node.handle = sock_connect(srv, port);
		if (node.handle <= 0) {
			printf("Unable to connect to %s:%d\n", srv, port);
		}
		else {
			while (sigtrap == 0 && node.finished == 0) {

				// continue to send data to the socket over and over as quickly as possible.
				while (node.out.length > 0) {
					assert(node.handle > 0);
					sent = sock_send(node.handle, node.out.data, node.out.length);
					if (sent < 0) { sigtrap ++; }
					else {
						assert(sent > 0);
						assert(sent <= node.out.length);
						if (sent == node.out.length) { expbuf_clear(&node.out); }
						else { expbuf_purge(&node.out, sent); }
					}	
				}

				// if we didn't generate a fail during the write, then we do a read.
				if (sigtrap == 0) {

					avail = node.in.max - node.in.length;
					if (avail < 1024) {
						expbuf_shrink(&node.in, 1024);
						avail = 1024;
					}

					sent = sock_receive(node.handle, node.in.data + node.in.length, avail);
					if (sent < 0) { sigtrap ++; }
					else {
						assert(sent > 0);
						node.in.length += sent;
						assert(node.in.length <= node.in.max);
						if (sent == avail) {
							// we filled the incoming buffer, so we need to double it.
							expbuf_shrink(&node.in, node.in.max * 2);
						}
						processed = risp_process(risp, &node, node.in.length, (unsigned char *) node.in.data);
// 						printf("Processed %d.\n", processed);
						if (processed > 0) {
							expbuf_purge(&node.in, processed);

							if (node.offset > 0 && node.size > 0) {
								t = (node.offset / (node.size/100));
								if (t > done) {
									done = t;
									printf("Done - %c%d\n", '%', done);
								}
							}
						}
					}
				}
			}
			
			// close the socket.
			if (node.handle >= 0) {
				close(node.handle);
			}
		}
	
		// clean up the risp structure.
		risp_shutdown(risp);
	}
	
	return 0;
}
Esempio n. 7
0
int ac_run()
{

	if (!conf_listen_addrs_len){
		cw_log(LOG_ERR,"Fatal error: No listen addresses found.");
		return 1;
	}



	/* it is important to create the unicast sockets first, 
	 * because when we create the mcast an bcast sockets next 
	 * we will look for already created sockets to find a
	 * good unicast reply socket */

	int i;
	for(i=0; i<conf_listen_addrs_len; i++){
		socklist_add_unicast(conf_listen_addrs[i],conf_control_port,AC_PROTO_CAPWAP);
#ifdef WITH_LWAPP
		if (conf_lwapp) 
			socklist_add_unicast(conf_listen_addrs[i],conf_lw_control_port,AC_PROTO_LWAPP);
#endif 
	}

	if (socklist_len==0){
		cw_log(LOG_ERR,"Fatal error: Could not setup any listen socket");
		return 1;
	}

	/* create multicast sockets */
	for (i=0; i<conf_mcast_groups_len;i++){
		socklist_add_multicast(conf_mcast_groups[i],conf_control_port,AC_PROTO_CAPWAP);
#ifdef WITH_LWAPP
		if (conf_lwapp) 
			socklist_add_multicast(conf_mcast_groups[i],conf_lw_control_port,AC_PROTO_LWAPP);
#endif 

	}

	/* broadcast sockety ipv4 only */
	for (i=0; i<conf_bcast_addrs_len;i++){
		socklist_add_broadcast(conf_bcast_addrs[i],conf_control_port,AC_PROTO_CAPWAP);
#ifdef WITH_LWAPP
//		printf("Adding %d\n",socklist_len);
		if (conf_lwapp) 
			socklist_add_broadcast(conf_bcast_addrs[i],conf_lw_control_port,AC_PROTO_LWAPP);
//		printf ("SI %d, PROTO: %d\n",socklist_len-1,socklist[socklist_len-1].ac_proto);
#endif 
	}



	get_acinfo();


	while(1){

		/* prepare fdset */
		fd_set fset;
		int max = 0;
		FD_ZERO(&fset);
		for (i=0; i<socklist_len; i++){
			FD_SET(socklist[i].sockfd,&fset);
			if (socklist[i].sockfd>max)
				max=socklist[i].sockfd;
		}

		/* wait for an event */
		int n;
	        while((n=select(max+1, &fset, NULL, NULL, NULL)) < 0) {
			if (errno != EINTR) 
				return n;

	        }

		/* process the received packet */
		for( i=0; i<socklist_len; i++){

			if (!FD_ISSET(socklist[i].sockfd,&fset))
				continue;

			struct sockaddr_storage srcaddr;
			socklen_t sockaddrlen;

			memset(&srcaddr,0,sizeof(struct sockaddr_storage));
			sockaddrlen = sizeof(struct sockaddr_storage);

			uint8_t buffer[4096];
			int len = sock_receive(socklist[i].sockfd,
					buffer, sizeof(buffer),
					0,
					(struct sockaddr*)&srcaddr, &sockaddrlen);

			process_ctrl_packet(i, (struct sockaddr*)&srcaddr,buffer,len);
		}

	}


	/* close and free all sockts */
	for(i=0; i<socklist_len; i++){
//		close(socklist[i]);
	}
	free(socklist);
	return 0;
}
Esempio n. 8
0
void *recv_thread(void *arg)
{
    int ret = EXIT_SUCCESS;

    char *message;
    int length = 0;

    fd_set fd_connect_set;
    struct timeval tv_connect_timeout;

    int addr_len = sizeof(struct sockaddr_in);

    message = recv_buffer;

    log(LOG_GENERIC, "recv thread created");

    while (1)
    {
        init_socket();

        while (1)
        {
            // try to bind local port
            log(LOG_GENERIC, "bind %s:%d...", 
                inet_ntoa(local_sck_addr.sin_addr), ntohs(local_sck_addr.sin_port));

            ret = bind(sck_fd, (struct sockaddr *)&local_sck_addr, sizeof(struct sockaddr_in));
            if (ret == 0)
            {
                log(LOG_GENERIC, "bind success");
            }
            else
            {
                log(LOG_ERROR, "bind err %d", ret);
            }

            // try to connect remote:
            log(LOG_GENERIC, "trying to connect %s:%d...",
                inet_ntoa(remote_sck_addr.sin_addr), ntohs(remote_sck_addr.sin_port));

            // force socket as non-blocking
            set_socket_blocking_enabled(sck_fd, false);

            ret = connect(sck_fd, (struct sockaddr *)&remote_sck_addr, sizeof(struct sockaddr_in));
            if (ret < 0)
            {
                if (WSAGetLastError() == WSAEWOULDBLOCK)	//EINPROGRESS
                {
                    tv_connect_timeout.tv_sec = 1; 
                    tv_connect_timeout.tv_usec = 0;

                    FD_ZERO(&fd_connect_set); 
                    FD_SET(sck_fd, &fd_connect_set);

                    // wait 1 seconds:
                    ret = select(sck_fd + 1, NULL, &fd_connect_set, NULL, &tv_connect_timeout);

                    if (ret <= 0)
                    {
                        log(LOG_GENERIC, "connect too slow, reinit socket");
                        deinit_socket();
                        init_socket();
                    }
                    else
                    { // connected
                        break;
                    }
                }
                else
                {
                    log(LOG_ERROR, "connect err %d", ret);
                }
            }
            else if (ret == 0)
            {
                break;
            }

            usleep(CONNECT_RETRY_DELAY);
        }

        // force socket as blocking
        set_socket_blocking_enabled(sck_fd, true);

        log(LOG_GENERIC, "connected");
        usleep(CONNECTED_DELAY);

        send_hunter_message(HUNT_MSG_CONNECTED);

        while (1)
        {
            // blocking socket:
            ret = recv(sck_fd, recv_buffer, MAX_SOCK_BUFFER, 0);
            if (ret > 0)
            {
                length = ret;
            }
            else if (ret == 0)
            {
                // orderly shutdown
                log(LOG_ERROR, "recv shutdown");
                break;
            }
            else
            { // ret < 0, typically -1
                // an error occurred
                log(LOG_ERROR, "recv error %d", ret);
            }

#ifdef sock_DEBUG
            log(LOG_GENERIC, "Receive %d:%s", length, message);
#endif // sock_DEBUG

            // once received, we call handler:
            sock_receive(message, length);

            // check how much time is wasted on receive module
        }

        log(LOG_GENERIC, "disconnect");

        // we should gently close socket, and try to connect again
        closesocket(sck_fd);
    }

    log(LOG_GENERIC, "recv thread exit");
}