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 }
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; }
/* * 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; }
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; }
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; }
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; }
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; }
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"); }