1 void main() 2 { 3 struct XUDPCB *xudpcb; 4 struct XUDPSCB *xudpscb; 5 struct XUDPCmd *pCmd; 6 int pidChild; 7 fd_set setFD; 8 int result; 9 struct timeval timestuff; 10 Timestamp ts; 11 Boolean dontwait=FALSE; 12 #ifdef STATLOG 13 Timestamp statts=0; 14 #endif 15 printf("xudpd: eXtended User Datagram Protocol handler\n"); 16 printf("[Initializing..."); 17 fflush(stdout); 18 19 if ( !(xudpscb=malloc(sizeof(struct XUDPSCB)))) 20 xudpError("xudpd: Allocating RAM"); 21 22 xudp_init(xudpscb); 23 24 printf("ok]\n"); 25 fflush(stdout); 26 27 while(1) /* Loop "forever" */ 28 { 29 if ( !(xudpcb=malloc(sizeof(struct XUDPCB)))) 30 xudpError("xudpd: Allocating RAM"); 31 32 printf("[Waiting for client..."); 33 fflush(stdout); 34 35 xudp_getnewuser(xudpcb, xudpscb); 36 37 printf("accepted client]\n"); 38 fflush(stdout); 39 40 /* FORK BELOW *****************************************************/ 41 42 #ifdef DONTFORK 43 /* DISABLE FORKING */ 44 pidChild=0; 45 #endif 46 #ifndef DONTFORK 47 if ((pidChild=fork())<0) xudpError("Trying to fork"); 48 else 49 #endif 50 51 if (pidChild==0) 52 { 53 /************************************************************** 54 * CONNECT Loop: Executes until either: 55 * 1) A foreign "xudpd" connects with us through 56 * the Internet 57 * 2) Our local user application wishes to place a 58 * call to a foreign host. 59 */ 60 while(!xudpcb->state) 61 { 62 xudp_handlecontrol(xudpcb, xudpscb); 63 } 64 65 #ifdef DEBUG 66 show_sockaddr_in(&xudpcb->hostaddr); 67 #endif 68 69 printf("[Default socket buffer size is 32K]\n"); 70 fflush(stdout); 71 xudp_socketinit(xudpcb); 72 73 xudpcb->state=XUDP_SOFT_START; 74 75 while(xudpcb->state) /* Main protocol loop *******************/ 76 { 77 #ifdef DEBUG 78 show_status(xudpcb); 79 #endif 80 #ifdef DELAY 81 sleep(1); 82 #endif 83 ts=makeTimestamp(); 84 if (ts-statts>=20) 85 { 86 statts=ts; 87 /* xudp_windowchange(xudpcb); */ 88 #ifdef STATLOG 89 fprintf(xudpcb->bytlog, "%u %lu\n", 90 xudpcb->timeElapsed, xudpcb->bytesACKed); 91 /* fflush(xudpcb->bytlog);*/ 92 fprintf(xudpcb->rttlog, "%u %u %f\n", 93 xudpcb->timeElapsed, 94 xudpcb->rtt, xudpcb->rttavg); 95 /* fflush(xudpcb->rttlog);*/ 96 fprintf(xudpcb->paclog, "%u %u\n", 97 xudpcb->timeElapsed,xudpcb->packetsInPipe); 98 /* fflush(xudpcb->paclog);*/ 99 #endif 100 } 101 xudpcb->timeElapsed=ts; 102 103 /** Just poll if the parcel outgoing queue has data */ 104 /** waiting in it AND there's room on the net for it */ 105 106 if (xudpcb->packetsInPipe<xudpcb->winRemote) 107 if (xudpcb->pOutHead->next!=NULL) 108 dontwait=TRUE; 109 110 /** Just poll if there's packets waiting to go out */ 111 112 if (xudpcb->pXmitQueue->next!=NULL) dontwait=TRUE; 113 114 pCmd=xudpcb->pCmdQueue->next; 115 while (pCmd!=NULL) 116 { 117 /* Make a command parcel if we're really waiting 118 around, flushes out commands that might be held in 119 our queue */ 120 121 if ((ts-xudpcb->pCmdQueue->next->timestamp)>=TIMEOUT) 122 { 123 xudp_makecommandparcel(xudpcb); 124 xudpcb->push=TRUE; 125 pCmd=NULL; 126 } 127 128 if (pCmd!=NULL) pCmd=pCmd->next; 129 } 130 131 /** Wait a reasonably long time for something on */ 132 /** either the UNIX stream or Internet UDP sockets - */ 133 /** saves system load, unless we're pushing a parcel */ 134 /** or just polling */ 135 136 if (!(xudpcb->push) && !(dontwait)) 137 { 138 result=0; 139 FD_ZERO(&setFD); 140 FD_SET(xudpcb->localclient->fdControl, &setFD); 141 FD_SET(xudpcb->fdCli, &setFD); 142 timestuff.tv_usec=1000*GRANULARITY*TIMEOUT; 143 timestuff.tv_sec=0; 144 if ((result=select(max(xudpcb->localclient->fdControl, 145 xudpcb->fdCli)+1, &setFD, NULL, 146 NULL, ×tuff))<0) 147 xudpError("select"); 148 } 149 else /* PUSH or DONTWAIT is set, do a quick poll */ 150 { 151 result=0; 152 FD_ZERO(&setFD); 153 FD_SET(xudpcb->localclient->fdControl, &setFD); 154 FD_SET(xudpcb->fdCli, &setFD); 155 timestuff.tv_usec=0; 156 timestuff.tv_sec=0; 157 if ((result=select(max(xudpcb->localclient->fdControl, 158 xudpcb->fdCli)+1, &setFD, NULL, 159 NULL, ×tuff))<0) 160 xudpError("select"); 161 } 162 dontwait=FALSE; 163 164 /** See if we're trying to close, if we are, close */ 165 /** after we've waited for everybody. */ 166 167 if (xudpcb->state==XUDP_CLOSE_WAIT) 168 if (makeTimestamp()-(xudpcb->closing)>=TIMECLOSE) 169 xudpcb->state=0; 170 if (xudpcb->state) 171 { 172 /****** Incoming Commands on UNIX Stream ***********/ 173 if (FD_ISSET(xudpcb->localclient->fdControl, &setFD)) 174 xudp_handlecontrol(xudpcb, xudpscb); 175 176 /****** Incoming packets from the network **********/ 177 /*** Queue on cb->pRecvQueue */ 178 if (FD_ISSET(xudpcb->fdCli, &setFD)) 179 xudp_recv(xudpcb); 180 181 /*** Move packets in cb->pRecvQueue to appropriate */ 182 /*** parcels in cb->pRecvWaitQueue and order them */ 183 xudp_organizeincoming(xudpcb); 184 185 /*** Mark ending packet sequence numbers on parcels */ 186 xudp_endparcel(xudpcb); 187 188 /*** Set the ACK flag on parcels that we've */ 189 /*** received an ACK for */ 190 xudp_recvackparcels(xudpcb); 191 192 /*** Set the ACK flag on individual packets that */ 193 /*** we've received an ACK for */ 194 xudp_recvackpackets(xudpcb); 195 196 /*** Queue up commands to ACKnowledge parcels that */ 197 /*** we've received in their entirety */ 198 xudp_ackparcels(xudpcb); 199 200 /*** Queue up commands to ACKnowledge individual */ 201 /*** packets based on various flow control */ 202 /*** algorithms */ 203 xudp_ackpackets(xudpcb); 204 205 /*** Reassemble fragmented RAW parcels to */ 206 /*** cb->pInHead formed by completed parcels in */ 207 /*** cb->pRecvWaitQueue */ 208 xudp_reassembleparcel(xudpcb); 209 210 /*** Fragment and queue up packets on */ 211 /*** cb->pXmitQueue to fill up our advertised */ 212 /*** window. Take packets from queued RAW parcels */ 213 /*** in cb->pOutHead. Insert waiting commands to */ 214 /*** be sent from cb->pCmdQueue */ 215 xudp_fragmentparcel(xudpcb); 216 217 /*** Send packets queued on cb->pXmitQueue and */ 218 /*** properly queue those packets on the list of */ 219 /*** packets waiting to receive acknowledgements */ 220 /*** (cb->pAckWaitQueue) */ 221 xudp_xmit(xudpcb); 222 223 /*** Blow completed RAW parcels on the cb->pInHead */ 224 /*** out to our XUDP application */ 225 xudp_dequeueparcel(xudpcb); 226 227 /*** Remove obsoleted parcels from the queues */ 228 xudp_removeobsolete(xudpcb); 229 230 /*** Retransmit packets that have exceeded their */ 231 /*** RTO's */ 232 xudp_retransmit(xudpcb); 233 } 234 } 235 236 /** Reset client connections, clean up the mess we've made */ 237 /** of RAM and prepare for next client. */ 238 xudp_loseuser(xudpcb); 239 240 /** Quit out of this child process */ 241 exit(0); 242 } /* end Child Process */ 243 244 } /* end "Loop Forever" */ 245 246 close(xudpscb->fdServ); 247 close(xudpscb->fdServAudio); 248 close(xudpscb->fdServVideo); 249 close(xudpscb->fdServControl); 250 free(xudpscb); 251 }
int xudp_init(struct XUDPSCB *scb);
1 int xudp_init(struct XUDPSCB *scb) 2 { 3 /* xudpd handles two connection points! 4 --------------------------------------- 5 1. It will bind itself to UDP/IP port SERVER_PORT as defined in 6 xudp.h. It will accept incoming connections, presumably from 7 foreign xudpd's. 8 9 2. It will bind itself to UNIX Streams CONTROL_UNIX, AUDIO_UNIX and 10 VIDEO_UNIX as defined in xudp.h. It will accept incoming connections, 11 presumably from local XUDP applications.*/ 12 13 /* Internet server side ************************************************/ 14 15 if ( (scb->fdServ=socket(AF_INET, SOCK_DGRAM, 0)) <0) 16 xudpError("xudp_init: socket(UDP)"); /* Opens a UDP/IP socket */ 17 18 /* Fill out address structure for server */ 19 20 scb->addrServ_in.sin_family=AF_INET; /* AF_INET is the Internet 21 Protocol Family. */ 22 scb->addrServ_in.sin_addr.s_addr=htonl(INADDR_ANY); 23 /* Will accept incoming 24 connections from any 25 address */ 26 27 /* Localhost UNIX Protocol server side *****************************/ 28 29 /* makeServer_un creates the UNIX stream sockets, binds them to the 30 specified pathnames and starts listening for connections */ 31 32 scb->fdServAudio=makeServer_un((struct sockaddr_un 33 *)&scb->addrServAudio_un, AUDIO_UNIX); 34 scb->fdServVideo=makeServer_un((struct sockaddr_un 35 *)&scb->addrServVideo_un, VIDEO_UNIX); 36 scb->fdServControl=makeServer_un((struct sockaddr_un 37 *)&scb->addrServControl_un, 38 CONTROL_UNIX); 39 return 0; 40 }
int xudp_getnewuser(struct XUDPCB *cb, struct XUDPSCB *scb);
1 int xudp_getnewuser(struct XUDPCB *cb, struct XUDPSCB *scb) 2 { 3 int un_len, i; 4 5 if ( !(cb->localclient=malloc(sizeof(struct XUDPHost)))) 6 xudpError("xudp_getnewuser: Allocating RAM"); 7 8 /******* Wait here until a local XUDP application registers with us */ 9 10 un_len=sizeof(cb->addrControl_un); 11 12 cb->localclient->fdControl=accept(scb->fdServControl, 13 (struct sockaddr *)&cb->addrControl_un, 14 &un_len); 15 /* Block until we accept (or we error 16 out) on an incoming UNIX connection. 17 The addressing information for the 18 client will be stored in addrControl_un */ 19 if (cb->localclient->fdControl<0) 20 xudpError("xudpd: Accepting connection (UNIX)"); 21 /* Check for errors */ 22 23 un_len=sizeof(cb->addrAudio_un); 24 cb->localclient->fdAudio=accept(scb->fdServAudio, 25 (struct sockaddr *)&cb->addrAudio_un, 26 &un_len); 27 if (cb->localclient->fdAudio<0) 28 xudpError("xudpd: Accepting connection (UNIX)"); 29 30 un_len=sizeof(cb->addrVideo_un); 31 cb->localclient->fdVideo=accept(scb->fdServVideo, 32 (struct sockaddr *)&cb->addrVideo_un, 33 &un_len); 34 if (cb->localclient->fdVideo<0) 35 xudpError("xudpd: Accepting connection (UNIX)"); 36 37 /*** Initialize the variables in the control block for this new */ 38 /*** application */ 39 40 cb->pOutHead=makeParcel(); 41 cb->pInHead=makeParcel(); 42 43 cb->pAckWaitQueue=makeFragParcel(); 44 cb->pRecvWaitQueue=makeFragParcel(); 45 46 cb->pCmdQueue=makeCmd(); 47 cb->pCmdInQueue=makeCmd(); 48 49 cb->pXmitQueue=makePacket(); 50 cb->pRecvQueue=makePacket(); 51 52 cb->pOutHead->parcel=0; 53 cb->pInHead->parcel=0; 54 cb->pAckWaitQueue->parcel=0; 55 cb->pRecvWaitQueue->parcel=0; 56 57 cb->mps=MPS; 58 cb->push=0; 59 cb->winAdvertised=MAXWINDOW; 60 cb->winCongestion=1; 61 cb->winRemote=MAXWINDOW; 62 cb->packetsInPipe=0; 63 cb->packetsInPipeRmt=0; 64 cb->rtt=1; 65 cb->rttavg=10.0; 66 cb->rttvar=20.0; 67 cb->rttmax=20.0; 68 cb->rttmin=0.0; 69 cb->rto=20; 70 cb->windowdelta=0.0; 71 72 for (i=0; i<MAXPARCEL; i++) 73 cb->usedparcels[i]=FALSE; 74 75 #ifdef SRLOG 76 cb->sendlog=fopen("send.log", "w"); 77 cb->recvlog=fopen("recv.log", "w"); 78 #endif 79 80 #ifdef STATLOG 81 cb->bytlog=fopen("stats.byt", "w"); 82 cb->rttlog=fopen("stats.rtt", "w"); 83 cb->paclog=fopen("stats.pac", "w"); 84 #endif 85 return 0; 86 }
int xudp_socketinit(struct XUDPCB *cb);
1 int xudp_socketinit(struct XUDPCB *cb) 2 { 3 int temp; 4 5 temp=SOCKBUFSIZE; /* Set up maximum socket-level buffers */ 6 if (setsockopt(cb->localclient->fdControl, SOL_SOCKET, SO_SNDBUF, 7 &temp, sizeof(int))<0) xudpError("xudp_socketinit"); 8 if (setsockopt(cb->localclient->fdControl, SOL_SOCKET, SO_RCVBUF, 9 &temp, sizeof(int))<0) xudpError("xudp_socketinit"); 10 if (setsockopt(cb->localclient->fdAudio, SOL_SOCKET, SO_SNDBUF, 11 &temp, sizeof(int))<0) xudpError("xudp_socketinit"); 12 if (setsockopt(cb->localclient->fdAudio, SOL_SOCKET, SO_RCVBUF, 13 &temp, sizeof(int))<0) xudpError("xudp_socketinit"); 14 if (setsockopt(cb->localclient->fdVideo, SOL_SOCKET, SO_SNDBUF, 15 &temp, sizeof(int))<0) xudpError("xudp_socketinit"); 16 if (setsockopt(cb->localclient->fdVideo, SOL_SOCKET, SO_RCVBUF, 17 &temp, sizeof(int))<0) xudpError("xudp_socketinit"); 18 if (setsockopt(cb->fdCli, SOL_SOCKET, SO_SNDBUF, &temp, 19 sizeof(int))<0) xudpError("xudp_socketinit"); 20 if (setsockopt(cb->fdCli, SOL_SOCKET, SO_RCVBUF, &temp, 21 sizeof(int))<0) xudpError("xudp_socketinit"); 22 23 if (fcntl(cb->fdCli, F_SETFL, FNDELAY)<0) 24 xudpError("xudp_socketinit"); 25 26 return 0; 27 }
int xudp_loseuser(struct XUDPCB *cb);
1 int xudp_loseuser(struct XUDPCB *cb) 2 { 3 xudpSendFunction(cb->localclient, F_CLOSE, NULL); 4 sleep(1); 5 close(cb->fdCli); 6 close(cb->localclient->fdControl); 7 close(cb->localclient->fdAudio); 8 close(cb->localclient->fdVideo); 9 free(cb->localclient); 10 11 while (cb->pAckWaitQueue->next!=NULL) 12 deleteFragParcel(cb->pAckWaitQueue->next); 13 deleteFragParcel(cb->pAckWaitQueue); 14 15 while (cb->pOutHead->next!=NULL) 16 deleteParcel(cb->pOutHead->next); 17 deleteParcel(cb->pOutHead); 18 19 while (cb->pRecvWaitQueue->next!=NULL) 20 deleteFragParcel(cb->pRecvWaitQueue->next); 21 deleteFragParcel(cb->pRecvWaitQueue); 22 23 while (cb->pInHead->next!=NULL) 24 deleteParcel(cb->pInHead->next); 25 deleteParcel(cb->pInHead); 26 27 while (cb->pXmitQueue->next!=NULL) 28 deletePacket(cb->pXmitQueue->next); 29 deletePacket(cb->pXmitQueue); 30 31 while (cb->pRecvQueue->next!=NULL) 32 deletePacket(cb->pRecvQueue->next); 33 deletePacket(cb->pRecvQueue); 34 35 while (cb->pCmdQueue->next!=NULL) 36 deleteCmd(cb->pCmdQueue->next); 37 deleteCmd(cb->pCmdQueue); 38 39 while (cb->pCmdInQueue->next!=NULL) 40 deleteCmd(cb->pCmdInQueue->next); 41 deleteCmd(cb->pCmdInQueue); 42 43 #ifdef SRLOG 44 fclose(cb->sendlog); 45 fclose(cb->recvlog); 46 #endif 47 #ifdef STATLOG 48 fclose(cb->bytlog); 49 fclose(cb->rttlog); 50 fclose(cb->paclog); 51 #endif 52 53 free(cb); 54 return 0; 55 }
int xudp_handlecontrol(struct XUDPCB *cb, struct XUDPSCB *scb);
1 int xudp_handlecontrol(struct XUDPCB *cb, struct XUDPSCB *scb) 2 { 3 int fcn=0; 4 u_short temp; 5 int in_len; 6 char buffer[25]; 7 struct sockaddr_in remoteaddr, localaddr; 8 fd_set setFD; 9 char t2; 10 struct XUDPCmd *pCmd; 11 12 fcn=xudpGetFunction(cb->localclient); 13 switch (fcn) 14 { 15 case F_CONNECT: 16 printf("[Received connection request]\n"); 17 fflush(stdout); 18 /* Opens a UDP/IP socket */ 19 if ((cb->fdCli=socket(AF_INET, SOCK_DGRAM, 0))<0) 20 xudpError("xudpd: socket(UDP)"); 21 localaddr.sin_family=AF_INET; 22 localaddr.sin_port=htons(0); 23 localaddr.sin_addr.s_addr=htonl(INADDR_ANY); 24 if ((bind(cb->fdCli, (struct sockaddr *)&localaddr, 25 sizeof(struct sockaddr_in)))<0) 26 xudpError("xudpd: bind(UDP)"); /* Sets up a unique port 27 number */ 28 29 streamRead(cb->localclient->fdControl, (char *) &cb->hostaddr, 30 sizeof(struct sockaddr_in)); 31 temp=0; 32 while (++temp<5) 33 { 34 if (sendto(cb->fdCli, "HELLO XUDP", 10, 0, 35 (struct sockaddr *)&cb->hostaddr, 36 sizeof(struct sockaddr_in))<0) 37 xudpError("sendto"); 38 sleep(1); 39 in_len=sizeof(struct sockaddr_in); 40 if (recvfrom(cb->fdCli, buffer, 10, 0, 41 (struct sockaddr *)&remoteaddr, &in_len)>0) 42 { 43 if (memcmp("HELLO XUDP", buffer, 10)==0) 44 { 45 temp=101; 46 /*** Grab the new port number */ 47 memcpy(&cb->hostaddr, &remoteaddr, 48 sizeof(struct sockaddr_in)); 49 /*** Connect with remote xudpd to gain system 50 level features */ 51 if (connect(cb->fdCli, 52 (struct sockaddr *)&cb->hostaddr, 53 sizeof(struct sockaddr_in))<0) 54 xudpError("connect"); 55 } 56 } 57 else xudpError("recvfrom"); 58 } 59 if (temp<100) /* No connect for 5 seconds */ 60 { 61 t2=ERR_NOCONNECT; 62 xudpSendFunction(cb->localclient, F_ERROR, (char *)&t2); 63 printf("[Aborted, no connect for 5 seconds]\n"); 64 close(cb->fdCli); 65 fflush(stdout); 66 } 67 else 68 { 69 printf("[Connected successfully]\n"); 70 fflush(stdout); 71 cb->state=XUDP_ESTABLISHED; 72 xudpSendFunction(cb->localclient, F_CONNECTED, 73 (char *)&cb->hostaddr); 74 sleep(1); 75 } 76 break; 77 case F_ACCEPT: 78 printf("[Waiting for foreign clients]\n"); 79 fflush(stdout); 80 81 /*** Wait for foreign xudpd to wake us up */ 82 FD_ZERO(&setFD); 83 FD_SET(scb->fdServ, &setFD); 84 85 /* Wait indefinitely for something on the UDP server socket */ 86 while(!cb->state) 87 { 88 temp=0; 89 if (select(scb->fdServ+1, &setFD, NULL, NULL, NULL)<0) 90 xudpError("select"); 91 in_len=sizeof(struct sockaddr_in); 92 if (recvfrom(scb->fdServ, buffer, 24, 0, 93 (struct sockaddr *)&remoteaddr, &in_len)>0) 94 { 95 if (memcmp("HELLO XUDP", buffer, 10)==0) 96 { 97 /* Opens a UDP/IP socket */ 98 if ((cb->fdCli=socket(AF_INET, SOCK_DGRAM, 0))<0) 99 xudpError("xudpd: socket(UDP)"); 100 localaddr.sin_family=AF_INET; 101 localaddr.sin_port=htons(0); 102 localaddr.sin_addr.s_addr=htonl(INADDR_ANY); 103 if (bind(cb->fdCli, (struct sockaddr *)&localaddr, 104 sizeof(struct sockaddr_in))<0) 105 xudpError("xudpd: bind"); 106 /* Sets up a unique port number */ 107 memcpy(&cb->hostaddr, &remoteaddr, 108 sizeof(struct sockaddr_in)); 109 if (sendto(cb->fdCli, "HELLO XUDP", 10, 0, 110 (struct sockaddr *)&cb->hostaddr, 111 sizeof(struct sockaddr_in))<0) 112 xudpError("sendto"); 113 if (connect(cb->fdCli, 114 (struct sockaddr *)&cb->hostaddr, 115 sizeof(struct sockaddr_in))<0) 116 xudpError("xudpd: connect"); 117 xudpSendFunction(cb->localclient, F_CONNECTED, 118 (char *)&cb->hostaddr); 119 cb->state=XUDP_ESTABLISHED; 120 } 121 } 122 } 123 break; 124 case F_BIND: 125 printf("[Binding local address]\n"); 126 fflush(stdout); 127 streamRead(cb->localclient->fdControl, (char *) &temp, 128 sizeof(u_short)); 129 if (temp==0) scb->addrServ_in.sin_port=htons(SERVER_PORT); 130 else scb->addrServ_in.sin_port=htons(temp); 131 132 in_len=sizeof(struct sockaddr_in); 133 134 if (bind(scb->fdServ, (struct sockaddr *)&(scb->addrServ_in), 135 in_len)<0 ) 136 xudpError("xudpd: bind()");/* We "bind" the server 137 to the information 138 in xudpserver->Addr */ 139 break; 140 case F_LISTEN: 141 printf("[Listening for foreign clients]\n"); 142 fflush(stdout); 143 listen(scb->fdServ, 1);/* Listen for clients, holding at most 1 144 in the queue */ 145 break; 146 case F_CLOSE: 147 cb->state=XUDP_CLOSE_WAIT; 148 cb->closing=makeTimestamp(); 149 pCmd=makeCmd(); 150 pCmd->cmd=C_CLOSE; 151 cb->push=TRUE; 152 break; 153 case F_SENDVIDEO: 154 xudp_queueparcel(cb, VIDEO); 155 break; 156 case F_SENDAUDIO: 157 xudp_queueparcel(cb, AUDIO); 158 break; 159 default: break; 160 } 161 return 0; 162 }