📄 tcp.lst
字号:
218
219
220
221
222 //------------------------------------------------------------------------
223 // This runs every 0.5 seconds. If the connection has had no activity
224 // it initiates closing the connection.
225 //
226 //------------------------------------------------------------------------
227 void tcp_inactivity(void)
228 {
229 1 UCHAR idata nr;
230 1
231 1 // Look for active connections in the established state
232 1 for (nr = 0; nr < 5; nr++)
233 1 {
234 2 if ((conxn[nr].ipaddr != 0) &&
235 2 (conxn[nr].state == STATE_ESTABLISHED) &&
236 2 (conxn[nr].inactivity))
237 2 {
238 3 // Decrement the timer and see if it hit 0
239 3 conxn[nr].inactivity--;
240 3 if (conxn[nr].inactivity == 0)
241 3 {
C51 COMPILER V7.06 TCP 06/26/2004 13:41:26 PAGE 5
242 4 // Inactivity timer has just timed out.
243 4 // Initiate close of connection
244 4 tcp_send((FLG_ACK | FLG_FIN), 20, nr);
245 4 conxn[nr].my_sequence++; // For my FIN
246 4 conxn[nr].state = STATE_FIN_WAIT_1;
247 4 // if (debug) printf("TCP: Entered FIN_WAIT_1 state\n");
248 4 }
249 3 }
250 2 }
251 1 }
252
253
254
255 //------------------------------------------------------------------------
256 // This handles incoming TCP messages and manages the TCP state machine
257 // Note - both the SYN and FIN flags consume a sequence number.
258 // See "TCP/IP Illustrated, Volume 1" Sect 18.6 for info on TCP states
259 // See "TCP/IP Illustrated, Volume 1" Sect 17.3 for info on flags
260 //------------------------------------------------------------------------
261 void tcp_rcve(UCHAR xdata * inbuf, UINT len)
262 {
263 1 UCHAR idata i, j, nr;
264 1 UINT idata result, header_len, data_len;
265 1 TCP_HEADER xdata * tcp;
266 1 IP_HEADER xdata * ip;
267 1 ULONG idata sum;
268 1
269 1 // IP header is always 20 bytes so message starts at index 34
270 1 tcp = (TCP_HEADER xdata *)(inbuf + 34);
271 1 ip = (IP_HEADER xdata *)(inbuf + 14);
272 1
273 1 // Compute TCP checksum including 12 byte pseudoheader
274 1 // Sum source_ipaddr, dest_ipaddr, and entire TCP message
275 1 sum = (ULONG)cksum(inbuf + 26, 8 + len);
276 1
277 1 // Add in the rest of pseudoheader which is
278 1 // protocol id and TCP segment length
279 1 sum += (ULONG)0x0006;
280 1 sum += (ULONG)len;
281 1
282 1 // In case there was a carry, add it back around
283 1 result = (UINT)(sum + (sum >> 16));
284 1
285 1 if (result != 0xFFFF)
286 1 {
287 2 // if (debug) printf("TCP: Error, bad cksum\n");
288 2 return;
289 2 }
290 1
291 1 // if (debug) printf("TCP: Msg rcvd with good cksum\n");
292 1
293 1 // See if message is for http server
294 1 if (tcp->dest_port != HTTP_PORT)
295 1 {
296 2 if (debug)
297 2 {
298 3 // printf("TCP: Error, msg to port\n ");
299 3 memset(text, 0, 10);
300 3 itoa(tcp->dest_port, text, 10);
301 3 // printf(text);
302 3 // printf("\n");
303 3 }
C51 COMPILER V7.06 TCP 06/26/2004 13:41:26 PAGE 6
304 2 tcp_send(FLG_RST, 20, NO_CONNECTION);
305 2 return;
306 2 }
307 1
308 1 // Capture sender's IP address and port number
309 1 sender_ipaddr = ip->source_ipaddr;
310 1 sender_tcpport = tcp->source_port;
311 1
312 1 // See if the TCP segment is from someone we are already
313 1 // connected to.
314 1 for (i=0; i < 5; i++)
315 1 {
316 2 if ((ip->source_ipaddr == conxn[i].ipaddr) &&
317 2 (tcp->source_port == conxn[i].port))
318 2 {
319 3 nr = i;
320 3 // if (debug) printf("TCP: Rcvd msg from existing conxn\n");
321 3 break;
322 3 }
323 2 }
324 1
325 1 // If i = 5, we are not connected. If it is a SYN then assign
326 1 // a temporary conection to it for processing
327 1 if (i == 5)
328 1 {
329 2 if (tcp->flags & FLG_SYN)
330 2 {
331 3 // Find first unused connection (one with IP = 0)
332 3 for (j=0; j < 5; j++)
333 3 {
334 4 if (conxn[j].ipaddr == 0)
335 4 {
336 5 nr = j;
337 5 // Initialize new connection
338 5 conxn[nr].state = STATE_LISTEN;
339 5 break;
340 5 }
341 4 }
342 3
343 3 // If all connections are used then drop msg
344 3 if (j == 5) return;
345 3
346 3 if (debug)
347 3 {
348 4 // printf("TCP: New connection ");
349 4 memset(text, 0, 10);
350 4 itoa((UINT)nr, text, 10);
351 4 // printf(text);
352 4 // printf("\n");
353 4 }
354 3 }
355 2 }
356 1
357 1
358 1 // By now we should have a connection number in range of 0-4
359 1 // Do a check to avoid any chance of exceeding size of struct
360 1 if (nr > 4)
361 1 {
362 2 // if (debug) printf("TCP: Error in assigning conxn number\n");
363 2 return;
364 2 }
365 1
C51 COMPILER V7.06 TCP 06/26/2004 13:41:26 PAGE 7
366 1 // Eventually put in protection against wrapping sequence
367 1 // numbers, for now make the client start over if his
368 1 // sequence number is close to wrapping
369 1 if (tcp->sequence > 0xFFFFFF00L)
370 1 {
371 2 // if (debug) printf("TCP: Rcvd a high sequence number\n");
372 2 conxn[nr].ipaddr = 0;
373 2 tcp_send(FLG_RST, 20, NO_CONNECTION);
374 2 return;
375 2 }
376 1
377 1 // Handle messages whose action is mostly independent of state
378 1 // such as RST, SYN, and segment with no ACK. That way the
379 1 // state machine below does not need to worry about it.
380 1 if (tcp->flags & FLG_RST)
381 1 {
382 2 // An RST does not depend on state at all. And it does
383 2 // not count as data so do not send an ACK here. Close
384 2 // connection
385 2 // if (debug) printf("TCP: Rcvd a reset\n");
386 2 conxn[nr].ipaddr = 0;
387 2 return;
388 2 }
389 1
390 1 else if (tcp->flags & FLG_SYN)
391 1 {
392 2 // A SYN segment only makes sense if connection is in LISTEN
393 2 if ((conxn[nr].state != STATE_LISTEN) &&
394 2 (conxn[nr].state != STATE_CLOSED))
395 2 {
396 3 // if (debug) printf("TCP: Error, rcvd bogus SYN\n");
397 3 conxn[nr].ipaddr = 0;
398 3 tcp_send(FLG_RST, 20, NO_CONNECTION);
399 3 return;
400 3 }
401 2 }
402 1
403 1 else if ((tcp->flags & FLG_ACK) == 0)
404 1 {
405 2 // Incoming segments except SYN or RST must have ACK bit set
406 2 // See TCP/IP Illustrated, Vol 2, Page 965
407 2 // Drop segment but do not send a reset
408 2 // if (debug) printf("TCP: Error, rcvd segment has no ACK\n");
409 2 return;
410 2 }
411 1
412 1 // Compute length of header including options, and from that
413 1 // compute length of actual data
414 1 header_len = (tcp->flags & 0xF000) >> 10;
415 1 data_len = len - header_len;
416 1
417 1
418 1
419 1 // Handle TCP state machine for this connection
420 1 switch (conxn[nr].state)
421 1 {
422 2 case STATE_CLOSED:
423 2 case STATE_LISTEN:
424 2
425 2 // If incoming segment contains SYN and no ACK, then handle
426 2 if ((tcp->flags & FLG_SYN) && ((tcp->flags & FLG_ACK) == 0))
427 2 {
C51 COMPILER V7.06 TCP 06/26/2004 13:41:26 PAGE 8
428 3 // Capture his starting sequence number and generate
429 3 // my starting sequence number
430 3 // Fill in connection information
431 3 conxn[nr].ipaddr = ip->source_ipaddr;
432 3 conxn[nr].port = tcp->source_port;
433 3 conxn[nr].state = STATE_LISTEN;
434 3 conxn[nr].his_sequence = 1 + tcp->sequence;
435 3 conxn[nr].his_ack = tcp->ack_number;
436 3
437 3 // Use system clock for initial sequence number
438 3 EA = 0;
439 3 conxn[nr].my_sequence = initial_sequence_nr;
440 3 initial_sequence_nr += 64000L;
441 3 EA = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -