📄 ts2udp.c
字号:
int fd, newfd;struct sockaddr_in *sock;{ int nfds, sd; fd_set ifds; register struct qbuf *qb; register struct udpconn *up; if (fd < 0 || fd >= maxpeers || peers[fd].udp_parent != fd) { errno = EINVAL; return NOTOK; } if (newfd) { FD_ZERO (&ifds); nfds = fd + 1; FD_SET (fd, &ifds); if (udp_select_socket (nfds, &ifds, NULLFD, NULLFD, OK) == NOTOK) return NOTOK; up = &peers[fd]; if ((qb = up -> udp_queue.qb_forw) == &up -> udp_queue) { errno = EWOULDBLOCK; return NOTOK; } if ((sd = dup (fd)) == NOTOK) return NOTOK; up = &peers[sd]; *sock = *((struct sockaddr_in *) qb -> qb_base); /* struct copy */ remque (qb); insque (qb, up -> udp_queue.qb_back); } else up = &peers[sd = fd]; up -> udp_parent = fd; bcopy ((char *) sock, (char *) &up -> udp_peer, sizeof up -> udp_peer); return (newfd ? sd : OK);}#endif /* if FALSE *//* *//* ********************************************************** * * * udp read socket * * * * This routine reads datagram messages on the DATAGRAM * * socket running over UDP/IP. The data is read into a * * buffer and queued on the qbuf struct passed on input. * * * * returns: # of bytes read * * * ********************************************************** */ int udp_read_socket (fd, q, secs, fromsock, td)int fd;struct qbuf *q;int secs;struct sockaddr_in *fromsock;struct TSAPdisconnect *td;{ int cc; int nfds; fd_set ifds, mask; struct qbuf qbuff; register struct qbuf *qb = &qbuff; register struct udpconn *up; struct sockaddr_in *sock; char *rbufptr; int i;#ifdef HULADEBUG printf ("\n in udp read socket \n");#endif/* * Check for valid socket descriptor and set the udpconn struct ptr. */ if (fd < 0 || fd >= maxpeers || (up = &peers[fd]) -> udp_parent == NOTOK) { errno = EINVAL; return tusaplose (td, DR_PARAMETER, NULLCP, TuErrString(UDERR_INVALID_XPORT_DESC)); }/* * Set up the file descriptor mask for the select. * Select will tell if the socket is readable if we set the * read mask. *//* * Make sure the queue is empty before reading more data. */ if ((qb = up -> udp_queue.qb_forw) == &up -> udp_queue) { FD_ZERO (&ifds);/* * Set the number of file descriptors we want to check. Select * examines the I/O descriptors in the bits 0 thru (nfds - 1) * so add 1 to get the file descriptor we want. */ nfds = fd + 1; FD_SET (fd, &mask);/* * Select the socket to determine if there is data that * can be read. The call to udp_select_socket not only * selects the socket but also dequeues any data onto the * read queue contained in the udpconn structure for the * active socket. */ for (ifds = mask ; ; ifds = mask) { if (udp_select_socket (nfds, /* # of fd's */ &ifds, /* & read mask */ NULLFD, /* & write mask */ NULLFD, /* & excptn mask */ secs) /* seconds wait */ == NOTOK) return tusaplose (td, DR_OPERATION, NULLCP, NULLCP); /* * Check if we dequeued any data. */ if ((qb = up -> udp_queue.qb_forw) != &up -> udp_queue) break; return tusaplose (td, DR_TIMER, NULLCP, NULLCP); } }/* * Remove the queue buffer from its queue and return it. */#ifdef HULADEBUG printf ("\n Removing the queued data from select\n");#endif remque (qb); /* * Format the qbuf with the real data info. */ q -> qb_len = qb -> qb_len; q -> qb_data = qb -> qb_data; q -> qb_base[0] = qb -> qb_base[0]; #ifdef HULADEBUG printf ("\n qb_data = \n"); for (cc=0; cc<25; cc++) printf (" %x ", *((qb -> qb_data) + cc) ); printf ("\n q_data = \n"); for (cc=0; cc<25; cc++) printf (" %x ", *((q -> qb_data) + cc) );#endif /* * Copy the fromsocket address saved in the udp peers array. */ bcopy ((char *) &up -> udp_peer, (char *) fromsock, sizeof up -> udp_peer); return qb -> qb_len;}/* *//* ********************************************************** * * * udp write socket * * * * This routine writes datagram messages on the DATAGRAM * * socket running over UDP/IP. The data is written from * * the qbuf buffer using the EXCELAN socket library call * * 'send'. * * * * returns: # of bytes written * * * ********************************************************** */int udp_write_socket (fd, data, cc, td)int fd;register char *data;int cc;struct TSAPdisconnect *td;{ register struct udpconn *up;int len;/* * Check for valid socket descriptor and set the * udpconn struct ptr for the socket. */ if (fd < 0 || fd >= maxpeers || (up = &peers[fd]) -> udp_parent == NOTOK#if FALSE || up -> udp_peer.sin_family == 0)#endif ) { errno = EINVAL; return NOTOK; }/* * Issue the write to the socket. It returns the number * of bytes written. */#ifdef HULADEBUG printf ("\n send datagram: "); printf (" socket = %d len = %d \n", fd, cc);#endif errno = 0; return send (fd, /* sd */ NULL, /* to addr */ data, /* buffer */ cc); /* buf size */ }/* */int udp_close (fd)int fd;{ register struct qbuf *qb, *qp; register struct udpconn *up, *vp;#ifdef HULADEBUG printf ("\n close socket: %d", fd);#endif #if FALSE if (fd < 0 || fd >= maxpeers || (up = &peers[fd]) -> udp_parent == NOTOK) { errno = EINVAL; return NOTOK; } up -> udp_parent = NOTOK; bzero ((char *) &up -> udp_peer, sizeof up -> udp_peer); for (qb = up -> udp_queue.qb_forw; qb != &up -> udp_queue; qb = qp) { qp = qb -> qb_forw; remque (qb); free ((char *) qb); } for (vp = (up = peers) + maxpeers; up < vp; up++) if (up -> udp_parent == fd) up -> udp_parent = up - peers;#endif return close (fd);}/* *//* ********************************************************** * * * udp select socket * * * * This routine handles doing the select to enable * * reading data on the socket. * * * * If data is readable on the socket, this routine will * * also do the actual read on the socket and queue the * * data on the udpconn struct read queue. * * * * synchronous multiplexing: * * * * secs < 0: block indefinitely * * secs = 0: poll * * secs > 0: wait for secs (in milliseconds) * * * * returns: OK, NOTOK * * * ********************************************************** */int udp_select_socket (nfds, rfds, wfds, efds, secs)int nfds;fd_set *rfds, *wfds, *efds;int secs;{ register int fd; int cc, len, mfds, result; fd_set ifds, jfds; register struct qbuf *qb; register struct udpconn *up, *vp; struct udpconn *wp; struct sockaddr_in *sock; char *recvptr;#ifdef HULADEBUG printf ("\n in udp select socket \n");#endif/* * Check if the read mask is set. Then check if any read masks * are set on each socket descriptor in the udpconn array. */ if (rfds) { jfds = *rfds; if (secs != OK)#ifdef HULADEBUG printf ("\n checking the read masks of all peers \n");#endif for (vp = (up = peers) + maxpeers, fd = 0; up < vp; up++, fd++) if (up -> udp_parent != NOTOK && FD_ISSET (fd, &jfds) && up -> udp_queue.qb_forw != &up -> udp_queue) { /* * We found data pending on this socket. */ secs = OK; break; } } /* end if rfds *//* * Now do the real select to enable reading the socket. * The 'selsocket' routine is a front end routine that * implements the semantics of the Berkley select. */#ifdef HULADEBUG printf ("\n doing the select on the read mask \n");#endif if ((result = selsocket (nfds, rfds, wfds, efds, secs)) == NOTOK || rfds == NULLFD) return result;#ifdef HULADEBUG printf ("\n return from select # = %d\n", result);#endif ifds = *rfds;/* * Read the datagrams on each socket descriptor in the udpconn * array that has its read enable bit set. Each datagram message * is put on the respective read queue for the socket. */ if ((mfds = nfds) > maxpeers) mfds = maxpeers;/* * Cycle thru each socket in the peers array. */ for (fd = 0, up = peers; fd < mfds; fd++, up++) if (FD_ISSET (fd, &ifds)) { if (up -> udp_parent == NOTOK) continue;/* * Allocate a qbuf structure and socket structure and * data buffer for the max datagram size (8K over EXCELAN). * These are all allocated contiguously. */ if ( (qb = (struct qbuf *) malloc (sizeof *qb + sizeof *sock) ) == NULL) return NOTOK; if ( (recvptr = (char *) malloc (8*1024) ) == NULL) { free ((char *) qb); return NOTOK; }/* * Setup the socket and qbuf structures. */ sock = (struct sockaddr_in *) qb -> qb_base; len = sizeof *sock; qb -> qb_data = recvptr;/* * Do the DATAGRAM read on the socket to dequeue the * data into the qbuf data buffer. */#ifdef HULADEBUG printf ("\n datagram receive on sock %d \n", fd);#endif errno = 0; if (( cc = receive ( fd, /* sd */ sock, /* from addr */ qb -> qb_data, /* buffer */ (8*1024) /* buf size */ )) == NOTOK) { free ((char *) qb); return NOTOK; }/* * Update the actual count of the bytes read. */#ifdef HULADEBUG printf ("\n received datagram - %d bytes long \n", cc); printf ("\n data = \n"); for (len=0; len<25; len++) printf (" %x ", *((qb -> qb_data) + len) );#endif qb -> qb_len = cc;/* * Save the remote socket address in the udpconn struct * and put the data on its queue. */ bcopy ( (char *) sock, (char *) &up -> udp_peer, sizeof *sock);#ifdef HULADEBUG printf ("\n queueing data on the active socket\n");#endif insque (qb, up -> udp_queue.qb_back); continue;/* * If not for the current udpconn struct, then search the * peers array for the matching socket address and queue * the data on it. */ for (wp = (vp = peers) + maxpeers; vp < wp; vp++) if (vp != up && vp -> udp_parent == up -> udp_parent && bcmp ((char *) &vp -> udp_peer, (char *) sock, sizeof *sock) == 0) break; if (vp >= wp && (vp = &peers[up -> udp_parent]) -> udp_peer.sin_family != 0) { free ((char *) qb); continue; }#ifdef HULADEBUG printf ("\n queuing data on the found socket \n");#endif insque (qb, vp -> udp_queue.qb_back); } /* end if FDSET *//* * Now reset all the file descriptors since they get modified. */ for (vp = (up = peers) + maxpeers, fd = 0; up < vp; up++, fd++) if (up -> udp_parent != NOTOK && FD_ISSET (fd, &jfds)) if (up -> udp_queue.qb_forw != &up -> udp_queue) FD_SET (fd, rfds); else FD_CLR (fd, rfds); result = 0; ifds = *rfds; if (wfds) for (fd = 0; fd < nfds; fd++) if (FD_ISSET (fd, wfds)) FD_SET (fd, &ifds); if (efds) for (fd = 0; fd < nfds; fd++) if (FD_ISSET (fd, efds)) FD_SET (fd, &ifds); for (fd = 0; fd < nfds; fd++) if (FD_ISSET (fd, &ifds)) result++;/* * Return the count of sockets that were read. */ return result;}#endif /* if HULA */#endif /* if UDP */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -