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