TASK_DLLEXPORT int Task_wait_read(int fd, long msec) { Task *tp; struct timeval tv; fd_set set; int r; if (!canSwitch) { FD_ZERO(&set); FD_SET(fd, &set); calcTv(&tv, msec); r = t_select(FD_SETSIZE, &set, 0, 0, &tv); if (r > 0) return 0; else if (r == 0) return 1; else return r; } tp = currTask; FD_ZERO(&set); FD_SET(fd, &set); tv.tv_sec = tv.tv_usec = 0; r = t_select(FD_SETSIZE, &set, 0, 0, &tv); if (r != 0) { Task_yield(); if (r > 0) return 0; else return r; } FD_ZERO(&tp->rfileset); FD_SET(fd, &tp->rfileset); tp->wakeUp = calcWakeup(msec); removeFromList(tp); tp->isRead = 1; addToWait(tp); tp->isTimed = 0; Task_yield(); tp->isRead = 0; return tp->isTimed; }
/* FUNCTION: bsd_select() * * Synchronous I/O multiplexing (for sockets) * * PARAM1: nfds; IN - the number of fds to be checked in each set (readfds, * writefds, exceptfds): not used in this release * PARAM2: readfds; IN/OUT - fd set containing descriptors to be examined * for readiness to read (i.e. received data is present * and can be retreived by recv() or recvfrom() without * blocking); on successful return, will contain * only those descriptors that are ready to read * PARAM3: writefds; IN/OUT - fd set containing descriptors to be examined * for readiness to write (e.g. send() or sendto() could * succeed without blocking, or socket has connect()ed); * on successful return, will contain only those * descriptors that are ready to write * PARAM4: exceptfds; IN/OUT - fd set containing descriptors to be examined * for exceptional conditions (i.e. out-of-band data * pending on socket); on successful return * PARAM5: timeout; IN - ptr to a struct timeval, which should be set to * indicate the maximum interval to wait for any * descriptor(s) to become ready; may be NULL, indicating * that select() can wait indefinitely for any descriptor(s) * to become ready * RETURNS: if successful, the number of ready file descriptors in all * the fd sets (may be 0 if the timeout expired), or -1 if an * error occured. The error would be available via bsd_errno(s). */ int bsd_select(int nfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, BSD_TIMEVAL_T * timeout) { long ltv; /* timeout expressed in ticks */ long tps; /* local copy of TPS */ USE_ARG(nfds); if (timeout != NULL) { /* This turning of a struct timeval into a tick-count timeout * assumes that TPS (ticks-per-second) is a reasonably small * integer, and that tv_usec may be anywhere from 0 to one * million (i.e. any number of microseconds up to one second). * So we scale tv_usec from microseconds to something reasonable * based on TPS, multiply it by TPS, then scale it the rest of * the way to ticks-per-second. */ tps = TPS; if (tps >= 1000) { ltv = (((timeout->tv_usec + 50) / 100) * tps) / 10000; } else if (tps >= 100) { ltv = (((timeout->tv_usec + 500) / 1000) * tps) / 1000; } else if (tps >= 10) { ltv = (((timeout->tv_usec + 5000) / 10000) * tps) / 100; } else { ltv = (((timeout->tv_usec + 50000) / 100000) * tps) / 10; } ltv += (timeout->tv_sec * TPS); } else { /* * NULL timeout: wait indefinitely in t_select() */ ltv = -1; } return (t_select(readfds, writefds, exceptfds, ltv)); }
kii_socket_code_t socket_recv_cb( kii_socket_context_t* socket_context, char* buffer, size_t length_to_read, size_t* out_actual_length) { int res; int received; int total = 0; char *pBuf = NULL; context_t* ctx = (context_t*)socket_context->app_context; do { res = t_select((void *)handle, ctx->sock, 1000); if (res == A_OK) { #if CONNECT_SSL received = SSL_read(ssl, buffer, length_to_read); #else received = t_recv(handle, ctx->sock, buffer, length_to_read, 0); #endif if(received > 0) { total = received; break; } } } while (res == A_OK); if (total > 0) { *out_actual_length = total; return KII_SOCKETC_OK; } else { printf("failed to receive:\n"); // TOOD: could be 0 on success? *out_actual_length = 0; socket_close_cb(socket_context); return KII_SOCKETC_FAIL; } }
void tcp_echo_recv(void) { int len; /* length of recv data */ int e; /* error holder */ unsigned i; /* generic index */ int count; /* select return */ fd_set fd_recv; /* fd for recv */ fd_set fd_accept; /* fd for accept */ TCPCLIENT tmpclient = tcpq; struct sockaddr_in client; SOCKTYPE tmpsock; /* scratch socket */ if (elisten_sock == INVALID_SOCKET && tcpq == NULL) return; /* Echo not set up, don't bother */ #ifdef USE_FDS FD_ZERO(&fd_recv); FD_ZERO(&fd_accept); #endif /* select on all open data sockets */ i = 0; count = 0; #ifdef USE_FDS while (tmpclient) { if (tmpclient->sock != INVALID_SOCKET) { FD_SET(tmpclient->sock, &fd_recv); i++; } tmpclient=tmpclient->next; } #else while (tmpclient) { if (tmpclient->sock != INVALID_SOCKET) fd_recv.fd_array[i++] = tmpclient->sock ; tmpclient=tmpclient->next; } #endif /* USE_FDS */ #ifndef TCP_ZEROCOPY /* if we need to listen for server receives too */ #ifdef USE_FDS if (tcpecho_server && (esvr_sock != INVALID_SOCKET)) { FD_SET(esvr_sock, &fd_recv); } #else if (tcpecho_server) { if (esvr_sock != INVALID_SOCKET) fd_recv.fd_array[i++] = esvr_sock; } #endif /* USE_FDS */ #else /* if we need to close the server's active socket */ if (esvr_sock_close != FALSE) { if (esvr_sock != INVALID_SOCKET) { socketclose(esvr_sock); esvr_sock = INVALID_SOCKET; } esvr_sock_close = FALSE; } #endif /* TCP_ZEROCOPY */ #ifndef USE_FDS fd_recv.fd_count = i; #endif /* make this a short timeout since elisten may create soon */ if (elisten_sock != INVALID_SOCKET) { #ifdef USE_FDS FD_SET(elisten_sock, &fd_accept); #else fd_accept.fd_array[0] = elisten_sock; fd_accept.fd_count = 1; #endif /* USE_FDS */ count = t_select(&fd_recv, NULL, &fd_accept, 1); } else { if (i) /* if no fd_set sockets filled in, don't bother */ count = t_select(&fd_recv, NULL, NULL, 1); } /* While the t_select() was executing, commands can be * executed from cmd-prompt and sockets can be cleaned up. * Check for that. */ if (elisten_sock == INVALID_SOCKET && tcpq == NULL) return; /* Echo not set up, don't bother */ for (i = 0; i < fd_recv.fd_count; i++) { #ifdef USE_FDS tmpsock = FD_GET(i, &fd_recv); if (tmpsock == INVALID_SOCKET) continue; #else tmpsock = fd_recv.fd_array[i]; #endif /* USE_FDS */ /* Find out the client connection corresponding to this socket */ tmpclient = tcp_client_from_sock(tmpsock); /* try a receive. Pick buffer according to client or server */ if (tmpclient) /* found a client for this one */ len = recv(tmpsock, tmpclient->inbuf, ECHOBUFSIZE, 0); #ifndef TCP_ZEROCOPY else if (tmpsock == esvr_sock) len = recv(tmpsock, srv_inbuf, ECHOBUFSIZE, 0); #endif /* TCP_ZEROCOPY */ else { continue; } if (len < 0) { e = t_errno(tmpsock); if (e != EWOULDBLOCK) { if (tmpsock != esvr_sock) ns_printf(tmpclient->pio,"TCP echo recv error %d\n", e); else ns_printf(NULL,"TCP echo recv error %d\n", e); } } else if (len == 0) { ns_printf(NULL,"TCPECHO:socket closed by other side\n"); if (tmpsock == esvr_sock) { socketclose (tmpsock); esvr_sock = INVALID_SOCKET; } else { if (tmpclient == NULL) { dtrap(); } else { tmpclient->sock = INVALID_SOCKET ; tcp_client_del(tmpclient); } } } else /* if (len > 0) - got some echo data */ { #ifndef TCP_ZEROCOPY if (tmpsock == esvr_sock) { /* we must be server, send echo reply */ if (tcpecho_server) { e = send(esvr_sock, srv_inbuf, len, 0); if (e < 0) { /* Print the error to console */ e = t_errno(esvr_sock); ns_printf(NULL, "TCP echo server, error %d sending reply\n", e); } } } else /* not the server socket, must be client */ #endif /* TCP_ZEROCOPY */ { /* If not a bulk test, print info */ if (tmpclient->len <= ECHOBUFSIZE) { ns_printf(tmpclient->pio,"TCP echo reply from:%s, len:%d, reply:%lu", print_ipad(tmpclient->rhost), len, tmpclient->replies); ns_printf(tmpclient->pio,"\n%s",prompt); } else { u_long dataval; u_long * rxbuf = (u_long*)(tmpclient->inbuf); u_long * rxend = (u_long*)(tmpclient->inbuf + (len & ~3)); dataval = tmpclient->tot_rcvd/4; /* adjust for odd sized previous receives */ if (tmpclient->tot_rcvd & 3) { MEMMOVE(rxbuf, tmpclient->inbuf + (len & 3), len); rxend--; dataval++; /* ignore sliced word */ } while (rxbuf < rxend) { if (*rxbuf != dataval) { ns_printf(tmpclient->pio, "tcp_echo data error; got %lu, expected %lu\n", *rxbuf, dataval); } rxbuf++; dataval++; } } tmpclient->replies++; tmpclient->tot_rcvd += len; } } } /* if no server listen to poll, return now */ if (elisten_sock == INVALID_SOCKET) return; #ifdef NOTDEF MEMSET(&client, 0, sizeof(client)); client.sin_family = AF_INET; client.sin_addr.s_addr = INADDR_ANY; client.sin_port = htons(ECHO_PORT); #endif /* check for received echo connection on server */ len = sizeof(client); tmpsock = accept(elisten_sock, (struct sockaddr*)&client, &len); if (tmpsock != INVALID_SOCKET) { if (esvr_sock == INVALID_SOCKET) { esvr_sock = tmpsock; #ifdef TCP_ZEROCOPY t_setsockopt(esvr_sock, SOL_SOCKET, SO_CALLBACK, (void*)echo_svr_upcall, 0); #endif /* TCP_ZEROCOPY */ } else /* we already have a connection */ { dprintf("tcpecho: rejected extra connection\n"); socketclose(tmpsock); /* refuse to serve another */ } } }